PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/SheepShaver/src/emul_op.cpp

https://github.com/amade/SheepShaver_oldstuff
C++ | 492 lines | 411 code | 50 blank | 31 comment | 47 complexity | a056a59b94e4e856122fe587c069c1d0 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * emul_op.cpp - 68k opcodes for ROM patches
  3. *
  4. * SheepShaver (C) 1997-2008 Christian Bauer and Marc Hellwig
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include <stdio.h>
  21. #include "sysdeps.h"
  22. #include "main.h"
  23. #include "version.h"
  24. #include "prefs.h"
  25. #include "cpu_emulation.h"
  26. #include "xlowmem.h"
  27. #include "xpram.h"
  28. #include "timer.h"
  29. #include "adb.h"
  30. #include "sony.h"
  31. #include "disk.h"
  32. #include "cdrom.h"
  33. #include "scsi.h"
  34. #include "video.h"
  35. #include "audio.h"
  36. #include "ether.h"
  37. #include "serial.h"
  38. #include "clip.h"
  39. #include "extfs.h"
  40. #include "macos_util.h"
  41. #include "rom_patches.h"
  42. #include "rsrc_patches.h"
  43. #include "name_registry.h"
  44. #include "user_strings.h"
  45. #include "emul_op.h"
  46. #include "thunks.h"
  47. #define DEBUG 0
  48. #include "debug.h"
  49. // TVector of MakeExecutable
  50. static uint32 MakeExecutableTvec;
  51. /*
  52. * Execute EMUL_OP opcode (called by 68k emulator)
  53. */
  54. void EmulOp(M68kRegisters *r, uint32 pc, int selector)
  55. {
  56. D(bug("EmulOp %04x at %08x\n", selector, pc));
  57. switch (selector) {
  58. case OP_BREAK: // Breakpoint
  59. printf("*** Breakpoint\n");
  60. Dump68kRegs(r);
  61. break;
  62. case OP_XPRAM1: { // Read/write from/to XPRam
  63. uint32 len = r->d[3];
  64. uint8 *adr = Mac2HostAddr(r->a[3]);
  65. D(bug("XPRAMReadWrite d3: %08lx, a3: %p\n", len, adr));
  66. int ofs = len & 0xffff;
  67. len >>= 16;
  68. if (len & 0x8000) {
  69. len &= 0x7fff;
  70. for (uint32 i=0; i<len; i++)
  71. XPRAM[((ofs + i) & 0xff) + 0x1300] = *adr++;
  72. } else {
  73. for (uint32 i=0; i<len; i++)
  74. *adr++ = XPRAM[((ofs + i) & 0xff) + 0x1300];
  75. }
  76. break;
  77. }
  78. case OP_XPRAM2: // Read from XPRam
  79. r->d[1] = XPRAM[(r->d[1] & 0xff) + 0x1300];
  80. break;
  81. case OP_XPRAM3: // Write to XPRam
  82. XPRAM[(r->d[1] & 0xff) + 0x1300] = r->d[2];
  83. break;
  84. case OP_NVRAM1: { // Read from NVRAM
  85. int ofs = r->d[0];
  86. r->d[0] = XPRAM[ofs & 0x1fff];
  87. bool localtalk = !(XPRAM[0x13e0] || XPRAM[0x13e1]); // LocalTalk enabled?
  88. switch (ofs) {
  89. case 0x13e0: // Disable LocalTalk (use EtherTalk instead)
  90. if (localtalk)
  91. r->d[0] = 0x00;
  92. break;
  93. case 0x13e1:
  94. if (localtalk)
  95. r->d[0] = 0x01;
  96. break;
  97. case 0x13e2:
  98. if (localtalk)
  99. r->d[0] = 0x00;
  100. break;
  101. case 0x13e3:
  102. if (localtalk)
  103. r->d[0] = 0x0a;
  104. break;
  105. }
  106. break;
  107. }
  108. case OP_NVRAM2: // Write to NVRAM
  109. XPRAM[r->d[0] & 0x1fff] = r->d[1];
  110. break;
  111. case OP_NVRAM3: // Read/write from/to NVRAM
  112. if (r->d[3]) {
  113. r->d[0] = XPRAM[(r->d[4] + 0x1300) & 0x1fff];
  114. } else {
  115. XPRAM[(r->d[4] + 0x1300) & 0x1fff] = r->d[5];
  116. r->d[0] = 0;
  117. }
  118. break;
  119. case OP_FIX_MEMTOP: // Fixes MemTop in BootGlobs during startup
  120. D(bug("Fix MemTop\n"));
  121. WriteMacInt32(BootGlobsAddr - 20, RAMBase + RAMSize); // MemTop
  122. r->a[6] = RAMBase + RAMSize;
  123. break;
  124. case OP_FIX_MEMSIZE: { // Fixes physical/logical RAM size during startup
  125. D(bug("Fix MemSize\n"));
  126. uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4);
  127. WriteMacInt32(0x1ef8, RAMSize); // Physical RAM size
  128. WriteMacInt32(0x1ef4, RAMSize - diff); // Logical RAM size
  129. break;
  130. }
  131. case OP_FIX_BOOTSTACK: // Fixes boot stack pointer in boot 3 resource
  132. D(bug("Fix BootStack\n"));
  133. r->a[1] = r->a[7] = RAMBase + RAMSize * 3 / 4;
  134. break;
  135. case OP_SONY_OPEN: // Floppy driver functions
  136. r->d[0] = SonyOpen(r->a[0], r->a[1]);
  137. break;
  138. case OP_SONY_PRIME:
  139. r->d[0] = SonyPrime(r->a[0], r->a[1]);
  140. break;
  141. case OP_SONY_CONTROL:
  142. r->d[0] = SonyControl(r->a[0], r->a[1]);
  143. break;
  144. case OP_SONY_STATUS:
  145. r->d[0] = SonyStatus(r->a[0], r->a[1]);
  146. break;
  147. case OP_DISK_OPEN: // Disk driver functions
  148. r->d[0] = DiskOpen(r->a[0], r->a[1]);
  149. break;
  150. case OP_DISK_PRIME:
  151. r->d[0] = DiskPrime(r->a[0], r->a[1]);
  152. break;
  153. case OP_DISK_CONTROL:
  154. r->d[0] = DiskControl(r->a[0], r->a[1]);
  155. break;
  156. case OP_DISK_STATUS:
  157. r->d[0] = DiskStatus(r->a[0], r->a[1]);
  158. break;
  159. case OP_CDROM_OPEN: // CD-ROM driver functions
  160. r->d[0] = CDROMOpen(r->a[0], r->a[1]);
  161. break;
  162. case OP_CDROM_PRIME:
  163. r->d[0] = CDROMPrime(r->a[0], r->a[1]);
  164. break;
  165. case OP_CDROM_CONTROL:
  166. r->d[0] = CDROMControl(r->a[0], r->a[1]);
  167. break;
  168. case OP_CDROM_STATUS:
  169. r->d[0] = CDROMStatus(r->a[0], r->a[1]);
  170. break;
  171. case OP_AUDIO_DISPATCH: // Audio component functions
  172. r->d[0] = AudioDispatch(r->a[3], r->a[4]);
  173. break;
  174. case OP_SOUNDIN_OPEN: // Sound input driver functions
  175. r->d[0] = SoundInOpen(r->a[0], r->a[1]);
  176. break;
  177. case OP_SOUNDIN_PRIME:
  178. r->d[0] = SoundInPrime(r->a[0], r->a[1]);
  179. break;
  180. case OP_SOUNDIN_CONTROL:
  181. r->d[0] = SoundInControl(r->a[0], r->a[1]);
  182. break;
  183. case OP_SOUNDIN_STATUS:
  184. r->d[0] = SoundInStatus(r->a[0], r->a[1]);
  185. break;
  186. case OP_SOUNDIN_CLOSE:
  187. r->d[0] = SoundInClose(r->a[0], r->a[1]);
  188. break;
  189. case OP_ADBOP: // ADBOp() replacement
  190. ADBOp(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0])));
  191. break;
  192. case OP_INSTIME: // InsTime() replacement
  193. r->d[0] = InsTime(r->a[0], r->d[1]);
  194. break;
  195. case OP_RMVTIME: // RmvTime() replacement
  196. r->d[0] = RmvTime(r->a[0]);
  197. break;
  198. case OP_PRIMETIME: // PrimeTime() replacement
  199. r->d[0] = PrimeTime(r->a[0], r->d[0]);
  200. break;
  201. case OP_MICROSECONDS: // Microseconds() replacement
  202. Microseconds(r->a[0], r->d[0]);
  203. break;
  204. case OP_PUT_SCRAP: // PutScrap() patch
  205. PutScrap(ReadMacInt32(r->a[7] + 8), Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 12));
  206. break;
  207. case OP_GET_SCRAP: // GetScrap() patch
  208. GetScrap((void **)Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 12));
  209. break;
  210. case OP_DEBUG_STR: // DebugStr() shows warning message
  211. if (PrefsFindBool("nogui")) {
  212. uint8 *pstr = Mac2HostAddr(ReadMacInt32(r->a[7] + 4));
  213. char str[256];
  214. int i;
  215. for (i=0; i<pstr[0]; i++)
  216. str[i] = pstr[i+1];
  217. str[i] = 0;
  218. WarningAlert(str);
  219. }
  220. break;
  221. case OP_INSTALL_DRIVERS: { // Patch to install our own drivers during startup
  222. // Install drivers
  223. InstallDrivers();
  224. // Patch MakeExecutable()
  225. MakeExecutableTvec = FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable");
  226. D(bug("MakeExecutable TVECT at %08x\n", MakeExecutableTvec));
  227. WriteMacInt32(MakeExecutableTvec, NativeFunction(NATIVE_MAKE_EXECUTABLE));
  228. #if !EMULATED_PPC
  229. WriteMacInt32(MakeExecutableTvec + 4, (uint32)TOC);
  230. #endif
  231. // Patch DebugStr()
  232. static const uint8 proc_template[] = {
  233. M68K_EMUL_OP_DEBUG_STR >> 8, M68K_EMUL_OP_DEBUG_STR,
  234. 0x4e, 0x74, // rtd #4
  235. 0x00, 0x04
  236. };
  237. BUILD_SHEEPSHAVER_PROCEDURE(proc);
  238. WriteMacInt32(0x1dfc, proc);
  239. break;
  240. }
  241. case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc
  242. r->d[0] = (uint32)-1;
  243. PatchNameRegistry();
  244. InitCallUniversalProc();
  245. break;
  246. case OP_RESET: // Early in MacOS reset
  247. D(bug("*** RESET ***\n"));
  248. TimerReset();
  249. MacOSUtilReset();
  250. AudioReset();
  251. // Enable DR emulator (disabled for now)
  252. if (PrefsFindBool("jit68k") && 0) {
  253. D(bug("DR activated\n"));
  254. WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation
  255. WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE);
  256. WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE);
  257. WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE);
  258. WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE);
  259. memcpy((void *)DR_EMULATOR_BASE, (void *)(ROMBase + 0x370000), DR_EMULATOR_SIZE);
  260. MakeExecutable(0, DR_EMULATOR_BASE, DR_EMULATOR_SIZE);
  261. }
  262. break;
  263. case OP_IRQ: // Level 1 interrupt
  264. WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt
  265. r->d[0] = 0;
  266. if (HasMacStarted()) {
  267. if (InterruptFlags & INTFLAG_VIA) {
  268. ClearInterruptFlag(INTFLAG_VIA);
  269. #if !PRECISE_TIMING
  270. TimerInterrupt();
  271. #endif
  272. ExecuteNative(NATIVE_VIDEO_VBL);
  273. static int tick_counter = 0;
  274. if (++tick_counter >= 60) {
  275. tick_counter = 0;
  276. SonyInterrupt();
  277. DiskInterrupt();
  278. CDROMInterrupt();
  279. }
  280. r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc.
  281. }
  282. if (InterruptFlags & INTFLAG_SERIAL) {
  283. ClearInterruptFlag(INTFLAG_SERIAL);
  284. SerialInterrupt();
  285. }
  286. if (InterruptFlags & INTFLAG_ETHER) {
  287. ClearInterruptFlag(INTFLAG_ETHER);
  288. ExecuteNative(NATIVE_ETHER_IRQ);
  289. }
  290. if (InterruptFlags & INTFLAG_TIMER) {
  291. ClearInterruptFlag(INTFLAG_TIMER);
  292. TimerInterrupt();
  293. }
  294. if (InterruptFlags & INTFLAG_AUDIO) {
  295. ClearInterruptFlag(INTFLAG_AUDIO);
  296. AudioInterrupt();
  297. }
  298. if (InterruptFlags & INTFLAG_ADB) {
  299. ClearInterruptFlag(INTFLAG_ADB);
  300. ADBInterrupt();
  301. }
  302. } else
  303. r->d[0] = 1;
  304. break;
  305. case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement
  306. uint32 ret = ReadMacInt32(r->a[7]);
  307. uint16 sel = ReadMacInt16(r->a[7] + 4);
  308. r->a[7] += 6;
  309. // D(bug("SCSIDispatch(%d)\n", sel));
  310. int stack;
  311. switch (sel) {
  312. case 0: // SCSIReset
  313. WriteMacInt16(r->a[7], SCSIReset());
  314. stack = 0;
  315. break;
  316. case 1: // SCSIGet
  317. WriteMacInt16(r->a[7], SCSIGet());
  318. stack = 0;
  319. break;
  320. case 2: // SCSISelect
  321. case 11: // SCSISelAtn
  322. WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1)));
  323. stack = 2;
  324. break;
  325. case 3: // SCSICmd
  326. WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2))));
  327. stack = 6;
  328. break;
  329. case 4: // SCSIComplete
  330. WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8)));
  331. stack = 12;
  332. break;
  333. case 5: // SCSIRead
  334. case 8: // SCSIRBlind
  335. WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7])));
  336. stack = 4;
  337. break;
  338. case 6: // SCSIWrite
  339. case 9: // SCSIWBlind
  340. WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7])));
  341. stack = 4;
  342. break;
  343. case 10: // SCSIStat
  344. WriteMacInt16(r->a[7], SCSIStat());
  345. stack = 0;
  346. break;
  347. case 12: // SCSIMsgIn
  348. WriteMacInt16(r->a[7] + 4, 0);
  349. stack = 4;
  350. break;
  351. case 13: // SCSIMsgOut
  352. WriteMacInt16(r->a[7] + 2, 0);
  353. stack = 2;
  354. break;
  355. case 14: // SCSIMgrBusy
  356. WriteMacInt16(r->a[7], SCSIMgrBusy());
  357. stack = 0;
  358. break;
  359. default:
  360. printf("FATAL: SCSIDispatch: illegal selector\n");
  361. stack = 0;
  362. //!! SysError(12)
  363. }
  364. r->a[0] = ret;
  365. r->a[7] += stack;
  366. break;
  367. }
  368. case OP_SCSI_ATOMIC: // SCSIAtomic() replacement
  369. D(bug("SCSIAtomic\n"));
  370. r->d[0] = (uint32)-7887;
  371. break;
  372. case OP_CHECK_SYSV: { // Check we are not using MacOS < 8.1 with a NewWorld ROM
  373. r->a[1] = r->d[1];
  374. r->a[0] = ReadMacInt32(r->d[1]);
  375. uint32 sysv = ReadMacInt16(r->a[0]);
  376. D(bug("Detected MacOS version %d.%d.%d\n", (sysv >> 8) & 0xf, (sysv >> 4) & 0xf, sysv & 0xf));
  377. if (ROMType == ROMTYPE_NEWWORLD && sysv < 0x0801)
  378. r->d[1] = 0;
  379. break;
  380. }
  381. case OP_NTRB_17_PATCH:
  382. r->a[2] = ReadMacInt32(r->a[7]);
  383. r->a[7] += 4;
  384. if (ReadMacInt16(r->a[2] + 6) == 17)
  385. PatchNativeResourceManager();
  386. break;
  387. case OP_NTRB_17_PATCH2:
  388. r->a[7] += 8;
  389. PatchNativeResourceManager();
  390. break;
  391. case OP_NTRB_17_PATCH3:
  392. r->a[2] = ReadMacInt32(r->a[7]);
  393. r->a[7] += 4;
  394. D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
  395. if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
  396. PatchNativeResourceManager();
  397. break;
  398. case OP_NTRB_17_PATCH4:
  399. r->d[0] = ReadMacInt16(r->a[7]);
  400. r->a[7] += 2;
  401. D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6)));
  402. if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17)
  403. PatchNativeResourceManager();
  404. break;
  405. case OP_CHECKLOAD: { // vCheckLoad() patch
  406. uint32 type = ReadMacInt32(r->a[7]);
  407. r->a[7] += 4;
  408. int16 id = ReadMacInt16(r->a[2]);
  409. if (r->a[0] == 0)
  410. break;
  411. uint32 adr = ReadMacInt32(r->a[0]);
  412. if (adr == 0)
  413. break;
  414. uint16 *p = (uint16 *)Mac2HostAddr(adr);
  415. uint32 size = ReadMacInt32(adr - 8) & 0xffffff;
  416. CheckLoad(type, id, p, size);
  417. break;
  418. }
  419. case OP_EXTFS_COMM: // External file system routines
  420. WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4)));
  421. break;
  422. case OP_EXTFS_HFS:
  423. WriteMacInt16(r->a[7] + 20, ExtFSHFS(ReadMacInt32(r->a[7] + 16), ReadMacInt16(r->a[7] + 14), ReadMacInt32(r->a[7] + 10), ReadMacInt32(r->a[7] + 6), ReadMacInt16(r->a[7] + 4)));
  424. break;
  425. case OP_IDLE_TIME:
  426. // Sleep if no events pending
  427. if (ReadMacInt32(0x14c) == 0)
  428. idle_wait();
  429. r->a[0] = ReadMacInt32(0x2b6);
  430. break;
  431. case OP_IDLE_TIME_2:
  432. // Sleep if no events pending
  433. if (ReadMacInt32(0x14c) == 0)
  434. idle_wait();
  435. r->d[0] = (uint32)-2;
  436. break;
  437. default:
  438. printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector);
  439. QuitEmulator();
  440. break;
  441. }
  442. }