void EtherInterrupt(void) { #if SUPPORTS_UDP_TUNNEL if (udp_tunnel_active) { EthernetPacket ether_packet; uint32 packet = ether_packet.addr(); ssize_t length; // Read packets from socket and hand to ether_udp_read() for processing while (true) { struct sockaddr_in from; socklen_t from_len = sizeof(from); length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len); if (length < 14) break; ether_udp_read(packet, length, &from); } } #endif }
status_t MacWindow::tick_func(void *arg) { MacWindow *obj = (MacWindow *)arg; static int tick_counter = 0; while (obj->tick_thread_active) { tick_counter++; if (tick_counter >= obj->frame_skip) { tick_counter = 0; // Window title is determined by Scroll Lock state uint32 scroll_lock_state = modifiers() & B_SCROLL_LOCK; if (scroll_lock_state != obj->old_scroll_lock_state) { if (scroll_lock_state) obj->SetTitle(GetString(STR_WINDOW_TITLE_FROZEN)); else obj->SetTitle(GetString(STR_WINDOW_TITLE)); obj->old_scroll_lock_state = scroll_lock_state; } // Has the Mac started? if (HasMacStarted()) { // Yes, set new cursor image if it was changed if (memcmp(MacCursor+4, Mac2HostAddr(0x844), 64)) { Mac2Host_memcpy(MacCursor+4, 0x844, 64); // Cursor image MacCursor[2] = ReadMacInt8(0x885); // Hotspot MacCursor[3] = ReadMacInt8(0x887); be_app->SetCursor(MacCursor); } } // Refresh screen unless Scroll Lock is down if (!scroll_lock_state) { obj->PostMessage(MSG_REDRAW); } } snooze(16666); } return 0; }
void NQD_fillrect(uint32 p) { D(bug("accl_fillrect %08x\n", p)); // Get filling parameters int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); uint32 color = htonl(ReadMacInt32(p + acclPenMode) == 8 ? ReadMacInt32(p + acclForePen) : ReadMacInt32(p + acclBackPen)); D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" width %d, height %d\n", width, height)); D(bug(" bytes_per_row %d color %08x\n", (int32)ReadMacInt32(p + acclDestRowBytes), color)); // And perform the fill const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); width *= bpp; switch (bpp) { case 1: for (int i = 0; i < height; i++) { memset(dest, color, width); dest += dest_row_bytes; } break; case 2: for (int i = 0; i < height; i++) { do_fillrect<16>(dest, color, width); dest += dest_row_bytes; } break; case 4: for (int i = 0; i < height; i++) { do_fillrect<32>(dest, color, width); dest += dest_row_bytes; } break; } }
void NQD_invrect(uint32 p) { D(bug("accl_invrect %08x\n", p)); // Get inversion parameters int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" width %d, height %d, bytes_per_row %d\n", width, height, (int32)ReadMacInt32(p + acclDestRowBytes))); //!!?? pen_mode == 14 // And perform the inversion const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); width *= bpp; switch (bpp) { case 1: for (int i = 0; i < height; i++) { do_invrect<8>(dest, width); dest += dest_row_bytes; } break; case 2: for (int i = 0; i < height; i++) { do_invrect<16>(dest, width); dest += dest_row_bytes; } break; case 4: for (int i = 0; i < height; i++) { do_invrect<32>(dest, width); dest += dest_row_bytes; } break; } }
__saveds void ASERDPort::serial_func(void) { struct ASERDPort *obj = (ASERDPort *)proc_arg; struct MsgPort *proc_port = NULL, *io_port = NULL, *control_port = NULL; struct IOExtSer *read_io = NULL, *write_io = NULL, *control_io = NULL; uint8 orig_params[sizeof(struct IOExtSer)]; bool opened = false; ULONG io_mask = 0, proc_port_mask = 0; // Default: error occured obj->proc_error = true; // Create message port for communication with main task proc_port = CreateMsgPort(); if (proc_port == NULL) goto quit; proc_port_mask = 1 << proc_port->mp_SigBit; // Create message ports for serial.device I/O io_port = CreateMsgPort(); if (io_port == NULL) goto quit; io_mask = 1 << io_port->mp_SigBit; control_port = CreateMsgPort(); if (control_port == NULL) goto quit; // Create IORequests read_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer)); write_io = (struct IOExtSer *)CreateIORequest(io_port, sizeof(struct IOExtSer)); control_io = (struct IOExtSer *)CreateIORequest(control_port, sizeof(struct IOExtSer)); if (read_io == NULL || write_io == NULL || control_io == NULL) goto quit; read_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Avoid CheckIO() bug write_io->IOSer.io_Message.mn_Node.ln_Type = 0; control_io->IOSer.io_Message.mn_Node.ln_Type = 0; // Parse device name char dev_name[256]; ULONG dev_unit; if (sscanf(obj->device_name, "%[^/]/%ld", dev_name, &dev_unit) < 2) goto quit; // Open device if (obj->is_parallel) ((IOExtPar *)read_io)->io_ParFlags = PARF_SHARED; else read_io->io_SerFlags = SERF_SHARED | SERF_7WIRE; if (OpenDevice((UBYTE *) dev_name, dev_unit, (struct IORequest *)read_io, 0) || read_io->IOSer.io_Device == NULL) goto quit; opened = true; // Copy IORequests memcpy(write_io, read_io, sizeof(struct IOExtSer)); memcpy(control_io, read_io, sizeof(struct IOExtSer)); // Attach control_io to control_port and set default values control_io->IOSer.io_Message.mn_ReplyPort = control_port; if (!obj->is_parallel) { control_io->io_CtlChar = SER_DEFAULT_CTLCHAR; control_io->io_RBufLen = 64; control_io->io_ExtFlags = 0; control_io->io_Baud = 9600; control_io->io_BrkTime = 250000; control_io->io_ReadLen = control_io->io_WriteLen = 8; control_io->io_StopBits = 1; control_io->io_SerFlags = SERF_SHARED; control_io->IOSer.io_Command = SDCMD_SETPARAMS; DoIO((struct IORequest *)control_io); memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); } // Initialization went well, inform main task obj->proc_port = proc_port; obj->control_io = control_io; obj->proc_error = false; Signal(MainTask, SIGF_SINGLE); // Main loop for (;;) { // Wait for I/O and messages (CTRL_C is used for quitting the task) ULONG sig = Wait(proc_port_mask | io_mask | SIGBREAKF_CTRL_C); // Main task wants to quit us if (sig & SIGBREAKF_CTRL_C) break; // Main task sent a command to us if (sig & proc_port_mask) { struct SerMessage *msg; while (msg = (SerMessage *)GetMsg(proc_port)) { D(bug("serial_proc received %08lx\n", msg->what)); switch (msg->what) { case MSG_QUERY: control_io->IOSer.io_Command = SDCMD_QUERY; DoIO((struct IORequest *)control_io); D(bug(" query returned %08lx, actual %08lx\n", control_io->IOSer.io_Error, control_io->IOSer.io_Actual)); break; case MSG_SET_PARAMS: // Only send SDCMD_SETPARAMS when configuration has changed if (memcmp(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar))) { memcpy(orig_params, &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); memcpy(&(read_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); memcpy(&(write_io->io_CtlChar), &(control_io->io_CtlChar), (uint8 *)&(control_io->io_Status) - (uint8 *)&(control_io->io_CtlChar)); control_io->IOSer.io_Command = SDCMD_SETPARAMS; D(bug(" params %08lx %08lx %08lx %08lx %08lx %08lx\n", control_io->io_CtlChar, control_io->io_RBufLen, control_io->io_ExtFlags, control_io->io_Baud, control_io->io_BrkTime, *(uint32 *)((uint8 *)control_io + 76))); DoIO((struct IORequest *)control_io); D(bug(" set_parms returned %08lx\n", control_io->IOSer.io_Error)); } break; case MSG_SET_PAR_PARAMS: control_io->IOSer.io_Command = PDCMD_SETPARAMS; DoIO((struct IORequest *)control_io); D(bug(" set_par_parms returned %08lx\n", control_io->IOSer.io_Error)); break; case MSG_BREAK: control_io->IOSer.io_Command = SDCMD_BREAK; DoIO((struct IORequest *)control_io); D(bug(" break returned %08lx\n", control_io->IOSer.io_Error)); break; case MSG_RESET: control_io->IOSer.io_Command = CMD_RESET; DoIO((struct IORequest *)control_io); D(bug(" reset returned %08lx\n", control_io->IOSer.io_Error)); break; case MSG_KILL_IO: AbortIO((struct IORequest *)read_io); AbortIO((struct IORequest *)write_io); WaitIO((struct IORequest *)read_io); WaitIO((struct IORequest *)write_io); obj->read_pending = obj->write_pending = false; obj->read_done = obj->write_done = false; break; case MSG_PRIME_IN: read_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb; read_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); read_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount); read_io->IOSer.io_Actual = 0; read_io->IOSer.io_Command = CMD_READ; D(bug("serial_proc receiving %ld bytes from %08lx\n", read_io->IOSer.io_Length, read_io->IOSer.io_Data)); SendIO((struct IORequest *)read_io); break; case MSG_PRIME_OUT: { write_io->IOSer.io_Message.mn_Node.ln_Name = (char *)msg->pb; write_io->IOSer.io_Data = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); write_io->IOSer.io_Length = ReadMacInt32(msg->pb + ioReqCount); write_io->IOSer.io_Actual = 0; write_io->IOSer.io_Command = CMD_WRITE; D(bug("serial_proc transmitting %ld bytes from %08lx\n", write_io->IOSer.io_Length, write_io->IOSer.io_Data)); #if MONITOR bug("Sending serial data:\n"); uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); for (int i=0; i<len; i++) { bug("%02lx ", adr[i]); } bug("\n"); #endif SendIO((struct IORequest *)write_io); break; } } D(bug(" serial_proc replying\n")); ReplyMsg(msg); } } // I/O operation completed if (sig & io_mask) { struct IOExtSer *io; while (io = (struct IOExtSer *)GetMsg(io_port)) { if (io == read_io) { D(bug("read_io complete, %ld bytes received, error %ld\n", read_io->IOSer.io_Actual, read_io->IOSer.io_Error)); uint32 pb = (uint32)read_io->IOSer.io_Message.mn_Node.ln_Name; #if MONITOR bug("Receiving serial data:\n"); uint8 *adr = Mac2HostAddr(ReadMacInt32(msg->pb + ioBuffer)); for (int i=0; i<read_io->IOSer.io_Actual; i++) { bug("%02lx ", adr[i]); } bug("\n"); #endif WriteMacInt32(pb + ioActCount, read_io->IOSer.io_Actual); obj->conv_error(read_io, obj->input_dt); obj->read_done = true; SetInterruptFlag(INTFLAG_SERIAL); TriggerInterrupt(); } else if (io == write_io) { D(bug("write_io complete, %ld bytes sent, error %ld\n", write_io->IOSer.io_Actual, write_io->IOSer.io_Error)); uint32 pb = (uint32)write_io->IOSer.io_Message.mn_Node.ln_Name; WriteMacInt32(pb + ioActCount, write_io->IOSer.io_Actual); obj->conv_error(write_io, obj->output_dt); obj->write_done = true; SetInterruptFlag(INTFLAG_SERIAL); TriggerInterrupt(); } } } } quit: // Close everything if (opened) { if (CheckIO((struct IORequest *)write_io) == 0) { AbortIO((struct IORequest *)write_io); WaitIO((struct IORequest *)write_io); } if (CheckIO((struct IORequest *)read_io) == 0) { AbortIO((struct IORequest *)read_io); WaitIO((struct IORequest *)read_io); } CloseDevice((struct IORequest *)read_io); } if (control_io) DeleteIORequest(control_io); if (write_io) DeleteIORequest(write_io); if (read_io) DeleteIORequest(read_io); if (control_port) DeleteMsgPort(control_port); if (io_port) DeleteMsgPort(io_port); // Send signal to main task to confirm termination Forbid(); Signal(MainTask, SIGF_SINGLE); }
void sheepshaver_state::record_video(void) { if (!video_recording_state) return; video_recording_state->write_video_frame(Mac2HostAddr(video_state.screen_base), video_state.mac_pal); }
int main(int argc, char **argv) { char str[256]; int16 i16; HANDLE rom_fh; const char *rom_path; uint32 rom_size; DWORD actual; uint8 *rom_tmp; // Initialize variables RAMBase = 0; // Print some info printf(GetString(STR_ABOUT_TEXT1), VERSION_MAJOR, VERSION_MINOR); printf(" %s\n", GetString(STR_ABOUT_TEXT2)); // Read preferences PrefsInit(NULL, argc, argv); // Parse command line arguments for (int i=1; i<argc; i++) { if (strcmp(argv[i], "--help") == 0) { usage(argv[0]); } else if (argv[i][0] == '-') { fprintf(stderr, "Unrecognized option '%s'\n", argv[i]); usage(argv[0]); } } // Check we are using a Windows NT kernel >= 4.0 OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx(&osvi)) { ErrorAlert("Could not determine OS type"); QuitEmulator(); } win_os = osvi.dwPlatformId; win_os_major = osvi.dwMajorVersion; if (win_os != VER_PLATFORM_WIN32_NT || win_os_major < 4) { ErrorAlert(GetString(STR_NO_WIN32_NT_4)); QuitEmulator(); } // Check that drivers are installed if (!check_drivers()) QuitEmulator(); // Load win32 libraries KernelInit(); // FIXME: default to DIB driver if (getenv("SDL_VIDEODRIVER") == NULL) putenv("SDL_VIDEODRIVER=windib"); // Initialize SDL system int sdl_flags = 0; #ifdef USE_SDL_VIDEO sdl_flags |= SDL_INIT_VIDEO; #endif #ifdef USE_SDL_AUDIO sdl_flags |= SDL_INIT_AUDIO; #endif assert(sdl_flags != 0); if (SDL_Init(sdl_flags) == -1) { char str[256]; sprintf(str, "Could not initialize SDL: %s.\n", SDL_GetError()); ErrorAlert(str); goto quit; } atexit(SDL_Quit); #ifdef ENABLE_MON // Initialize mon mon_init(); #endif // Install SIGSEGV handler for CPU emulator if (!sigsegv_install_handler(sigsegv_handler)) { sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno)); ErrorAlert(str); goto quit; } // Initialize VM system vm_init(); // Get system info PVR = 0x00040000; // Default: 604 CPUClockSpeed = 100000000; // Default: 100MHz BusClockSpeed = 100000000; // Default: 100MHz TimebaseSpeed = 25000000; // Default: 25MHz PVR = 0x000c0000; // Default: 7400 (with AltiVec) D(bug("PVR: %08x (assumed)\n", PVR)); // Init system routines SysInit(); // Show preferences editor if (!PrefsFindBool("nogui")) if (!PrefsEditor()) goto quit; // Create areas for Kernel Data if (!kernel_data_init()) goto quit; kernel_data = (KernelData *)Mac2HostAddr(KERNEL_DATA_BASE); emulator_data = &kernel_data->ed; KernelDataAddr = KERNEL_DATA_BASE; D(bug("Kernel Data at %p (%08x)\n", kernel_data, KERNEL_DATA_BASE)); D(bug("Emulator Data at %p (%08x)\n", emulator_data, KERNEL_DATA_BASE + offsetof(KernelData, ed))); // Create area for DR Cache if (vm_mac_acquire(DR_EMULATOR_BASE, DR_EMULATOR_SIZE) < 0) { sprintf(str, GetString(STR_DR_EMULATOR_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } dr_emulator_area_mapped = true; if (vm_mac_acquire(DR_CACHE_BASE, DR_CACHE_SIZE) < 0) { sprintf(str, GetString(STR_DR_CACHE_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } dr_cache_area_mapped = true; DRCacheAddr = (uint32)Mac2HostAddr(DR_CACHE_BASE); D(bug("DR Cache at %p (%08x)\n", DRCacheAddr, DR_CACHE_BASE)); // Create area for SheepShaver data if (!SheepMem::Init()) { sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } // Create area for Mac ROM if (vm_mac_acquire(ROM_BASE, ROM_AREA_SIZE) < 0) { sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } ROMBase = ROM_BASE; ROMBaseHost = Mac2HostAddr(ROMBase); rom_area_mapped = true; D(bug("ROM area at %p (%08x)\n", ROMBaseHost, ROMBase)); // Create area for Mac RAM RAMSize = PrefsFindInt32("ramsize"); if (RAMSize < 8*1024*1024) { WarningAlert(GetString(STR_SMALL_RAM_WARN)); RAMSize = 8*1024*1024; } RAMBase = 0; if (vm_mac_acquire(RAMBase, RAMSize) < 0) { sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); ErrorAlert(str); goto quit; } RAMBaseHost = Mac2HostAddr(RAMBase); ram_area_mapped = true; D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase)); if (RAMBase > ROMBase) { ErrorAlert(GetString(STR_RAM_HIGHER_THAN_ROM_ERR)); goto quit; } // Load Mac ROM rom_path = PrefsFindString("rom"); rom_fh = CreateFile(rom_path && *rom_path ? rom_path : ROM_FILE_NAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (rom_fh == INVALID_HANDLE_VALUE) { rom_fh = CreateFile(ROM_FILE_NAME2, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (rom_fh == INVALID_HANDLE_VALUE) { ErrorAlert(GetString(STR_NO_ROM_FILE_ERR)); goto quit; } } printf(GetString(STR_READING_ROM_FILE)); rom_size = GetFileSize(rom_fh, NULL); rom_tmp = new uint8[ROM_SIZE]; ReadFile(rom_fh, (void *)rom_tmp, ROM_SIZE, &actual, NULL); CloseHandle(rom_fh); // Decode Mac ROM if (!DecodeROM(rom_tmp, actual)) { if (rom_size != 4*1024*1024) { ErrorAlert(GetString(STR_ROM_SIZE_ERR)); goto quit; } else { ErrorAlert(GetString(STR_ROM_FILE_READ_ERR)); goto quit; } } delete[] rom_tmp; // Initialize native timers timer_init(); // Initialize everything if (!InitAll(NULL)) goto quit; D(bug("Initialization complete\n")); // Write protect ROM vm_protect(ROMBaseHost, ROM_AREA_SIZE, VM_PAGE_READ); // Start 60Hz thread tick_thread_cancel = false; tick_thread_active = ((tick_thread = create_thread(tick_func)) != NULL); SetThreadPriority(tick_thread, THREAD_PRIORITY_ABOVE_NORMAL); D(bug("Tick thread installed (%ld)\n", tick_thread)); // Start NVRAM watchdog thread memcpy(last_xpram, XPRAM, XPRAM_SIZE); nvram_thread_cancel = false; nvram_thread_active = ((nvram_thread = create_thread(nvram_func, NULL)) != NULL); SetThreadPriority(nvram_thread, THREAD_PRIORITY_BELOW_NORMAL); D(bug("NVRAM thread installed (%ld)\n", nvram_thread)); // Get my thread ID and jump to ROM boot routine emul_thread = GetCurrentThread(); D(bug("Jumping to ROM\n")); #ifdef _MSC_VER __try { #endif jump_to_rom(ROMBase + 0x310000); #ifdef _MSC_VER } __except (main_exception_filter(GetExceptionInformation())) {} #endif D(bug("Returned from ROM\n")); quit: Quit(); return 0; }
static inline int vm_mac_release(uint32 addr, uint32 size) { return vm_release(Mac2HostAddr(addr), size); }
static inline int vm_mac_acquire(uint32 addr, uint32 size) { return vm_acquire_fixed(Mac2HostAddr(addr), size); }
// Disable multicast address int16 ether_del_multicast(uint32 pb) { return ether_do_del_multicast(Mac2HostAddr(pb + eMultiAddr)); }
// Disable multicast address void AO_disable_multicast(uint32 addr) { if (net_open) ether_do_del_multicast(Mac2HostAddr(addr)); }
// Add multicast address void AO_enable_multicast(uint32 addr) { if (net_open) ether_do_add_multicast(Mac2HostAddr(addr)); }
void EmulOp(M68kRegisters *r, uint32 pc, int selector) { D(bug("EmulOp %04x at %08x\n", selector, pc)); switch (selector) { case OP_BREAK: // Breakpoint printf("*** Breakpoint\n"); Dump68kRegs(r); break; case OP_XPRAM1: { // Read/write from/to XPRam uint32 len = r->d[3]; uint8 *adr = Mac2HostAddr(r->a[3]); D(bug("XPRAMReadWrite d3: %08lx, a3: %p\n", len, adr)); int ofs = len & 0xffff; len >>= 16; if (len & 0x8000) { len &= 0x7fff; for (uint32 i=0; i<len; i++) XPRAM[((ofs + i) & 0xff) + 0x1300] = *adr++; } else { for (uint32 i=0; i<len; i++) *adr++ = XPRAM[((ofs + i) & 0xff) + 0x1300]; } break; } case OP_XPRAM2: // Read from XPRam r->d[1] = XPRAM[(r->d[1] & 0xff) + 0x1300]; break; case OP_XPRAM3: // Write to XPRam XPRAM[(r->d[1] & 0xff) + 0x1300] = r->d[2]; break; case OP_NVRAM1: { // Read from NVRAM int ofs = r->d[0]; r->d[0] = XPRAM[ofs & 0x1fff]; bool localtalk = !(XPRAM[0x13e0] || XPRAM[0x13e1]); // LocalTalk enabled? switch (ofs) { case 0x13e0: // Disable LocalTalk (use EtherTalk instead) if (localtalk) r->d[0] = 0x00; break; case 0x13e1: if (localtalk) r->d[0] = 0x01; break; case 0x13e2: if (localtalk) r->d[0] = 0x00; break; case 0x13e3: if (localtalk) r->d[0] = 0x0a; break; } break; } case OP_NVRAM2: // Write to NVRAM XPRAM[r->d[0] & 0x1fff] = r->d[1]; break; case OP_NVRAM3: // Read/write from/to NVRAM if (r->d[3]) { r->d[0] = XPRAM[(r->d[4] + 0x1300) & 0x1fff]; } else { XPRAM[(r->d[4] + 0x1300) & 0x1fff] = r->d[5]; r->d[0] = 0; } break; case OP_FIX_MEMTOP: // Fixes MemTop in BootGlobs during startup D(bug("Fix MemTop\n")); WriteMacInt32(BootGlobsAddr - 20, RAMBase + RAMSize); // MemTop r->a[6] = RAMBase + RAMSize; break; case OP_FIX_MEMSIZE: { // Fixes physical/logical RAM size during startup D(bug("Fix MemSize\n")); uint32 diff = ReadMacInt32(0x1ef8) - ReadMacInt32(0x1ef4); WriteMacInt32(0x1ef8, RAMSize); // Physical RAM size WriteMacInt32(0x1ef4, RAMSize - diff); // Logical RAM size break; } case OP_FIX_BOOTSTACK: // Fixes boot stack pointer in boot 3 resource D(bug("Fix BootStack\n")); r->a[1] = r->a[7] = RAMBase + RAMSize * 3 / 4; break; case OP_SONY_OPEN: // Floppy driver functions r->d[0] = SonyOpen(r->a[0], r->a[1]); break; case OP_SONY_PRIME: r->d[0] = SonyPrime(r->a[0], r->a[1]); break; case OP_SONY_CONTROL: r->d[0] = SonyControl(r->a[0], r->a[1]); break; case OP_SONY_STATUS: r->d[0] = SonyStatus(r->a[0], r->a[1]); break; case OP_DISK_OPEN: // Disk driver functions r->d[0] = DiskOpen(r->a[0], r->a[1]); break; case OP_DISK_PRIME: r->d[0] = DiskPrime(r->a[0], r->a[1]); break; case OP_DISK_CONTROL: r->d[0] = DiskControl(r->a[0], r->a[1]); break; case OP_DISK_STATUS: r->d[0] = DiskStatus(r->a[0], r->a[1]); break; case OP_CDROM_OPEN: // CD-ROM driver functions r->d[0] = CDROMOpen(r->a[0], r->a[1]); break; case OP_CDROM_PRIME: r->d[0] = CDROMPrime(r->a[0], r->a[1]); break; case OP_CDROM_CONTROL: r->d[0] = CDROMControl(r->a[0], r->a[1]); break; case OP_CDROM_STATUS: r->d[0] = CDROMStatus(r->a[0], r->a[1]); break; case OP_AUDIO_DISPATCH: // Audio component functions r->d[0] = gMacAudio->Dispatch(r->a[3], r->a[4]); break; case OP_SOUNDIN_OPEN: // Sound input driver functions r->d[0] = gMacAudio->InOpen(r->a[0], r->a[1]); break; case OP_SOUNDIN_PRIME: r->d[0] = gMacAudio->InPrime(r->a[0], r->a[1]); break; case OP_SOUNDIN_CONTROL: r->d[0] = gMacAudio->InControl(r->a[0], r->a[1]); break; case OP_SOUNDIN_STATUS: r->d[0] = gMacAudio->InStatus(r->a[0], r->a[1]); break; case OP_SOUNDIN_CLOSE: r->d[0] = gMacAudio->InClose(r->a[0], r->a[1]); break; case OP_ADBOP: // ADBOp() replacement gADBInput->Op(r->d[0], Mac2HostAddr(ReadMacInt32(r->a[0]))); break; case OP_INSTIME: // InsTime() replacement r->d[0] = InsTime(r->a[0], r->d[1]); break; case OP_RMVTIME: // RmvTime() replacement r->d[0] = RmvTime(r->a[0]); break; case OP_PRIMETIME: // PrimeTime() replacement r->d[0] = PrimeTime(r->a[0], r->d[0]); break; case OP_MICROSECONDS: // Microseconds() replacement Microseconds(r->a[0], r->d[0]); break; case OP_PUT_SCRAP: // PutScrap() patch PutScrap(ReadMacInt32(r->a[7] + 8), Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 12)); break; case OP_GET_SCRAP: // GetScrap() patch GetScrap((void **)Mac2HostAddr(ReadMacInt32(r->a[7] + 4)), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 12)); break; case OP_DEBUG_STR: // DebugStr() shows warning message if (PrefsFindBool("nogui")) { uint8 *pstr = Mac2HostAddr(ReadMacInt32(r->a[7] + 4)); char str[256]; int i; for (i=0; i<pstr[0]; i++) str[i] = pstr[i+1]; str[i] = 0; WarningAlert(str); } break; case OP_INSTALL_DRIVERS: { // Patch to install our own drivers during startup // Install drivers InstallDrivers(); // Patch MakeExecutable() MakeExecutableTvec = FindLibSymbol("\023PrivateInterfaceLib", "\016MakeExecutable"); D(bug("MakeExecutable TVECT at %08x\n", MakeExecutableTvec)); WriteMacInt32(MakeExecutableTvec, NativeFunction(NATIVE_MAKE_EXECUTABLE)); #if defined(__powerpc__) /* Native PowerPC */ WriteMacInt32(MakeExecutableTvec + 4, (uint32)TOC); #endif // Patch DebugStr() static const uint8 proc_template[] = { M68K_EMUL_OP_DEBUG_STR >> 8, M68K_EMUL_OP_DEBUG_STR & 0xFF, 0x4e, 0x74, // rtd #4 0x00, 0x04 }; BUILD_SHEEPSHAVER_PROCEDURE(proc); WriteMacInt32(0x1dfc, proc); break; } case OP_NAME_REGISTRY: // Patch Name Registry and initialize CallUniversalProc r->d[0] = (uint32)-1; PatchNameRegistry(); InitCallUniversalProc(); break; case OP_RESET: // Early in MacOS reset D(bug("*** RESET ***\n")); TimerReset(); MacOSUtilReset(); gMacAudio->Reset(); // Enable DR emulator (disabled for now) if (PrefsFindBool("jit68k") && 0) { D(bug("DR activated\n")); WriteMacInt32(KernelDataAddr + 0x17a0, 3); // Prepare for DR emulator activation WriteMacInt32(KernelDataAddr + 0x17c0, DR_CACHE_BASE); WriteMacInt32(KernelDataAddr + 0x17c4, DR_CACHE_SIZE); WriteMacInt32(KernelDataAddr + 0x1b04, DR_CACHE_BASE); WriteMacInt32(KernelDataAddr + 0x1b00, DR_EMULATOR_BASE); memcpy((void *)DR_EMULATOR_BASE, (void *)(ROMBase + 0x370000), DR_EMULATOR_SIZE); MakeExecutable(0, DR_EMULATOR_BASE, DR_EMULATOR_SIZE); } break; case OP_IRQ: // Level 1 interrupt WriteMacInt16(ReadMacInt32(KernelDataAddr + 0x67c), 0); // Clear interrupt r->d[0] = 0; if (HasMacStarted()) { if (InterruptFlags & INTFLAG_VIA) { ClearInterruptFlag(INTFLAG_VIA); #if !PRECISE_TIMING TimerInterrupt(); #endif ExecuteNative(NATIVE_VIDEO_VBL); static int tick_counter = 0; if (++tick_counter >= 60) { tick_counter = 0; SonyInterrupt(); DiskInterrupt(); CDROMInterrupt(); } r->d[0] = 1; // Flag: 68k interrupt routine executes VBLTasks etc. } if (InterruptFlags & INTFLAG_SERIAL) { ClearInterruptFlag(INTFLAG_SERIAL); SerialInterrupt(); } if (InterruptFlags & INTFLAG_ETHER) { ClearInterruptFlag(INTFLAG_ETHER); ExecuteNative(NATIVE_ETHER_IRQ); } if (InterruptFlags & INTFLAG_TIMER) { ClearInterruptFlag(INTFLAG_TIMER); TimerInterrupt(); } if (InterruptFlags & INTFLAG_AUDIO) { ClearInterruptFlag(INTFLAG_AUDIO); gMacAudio->Interrupt(); } if (InterruptFlags & INTFLAG_ADB) { ClearInterruptFlag(INTFLAG_ADB); gADBInput->Interrupt(); } } else r->d[0] = 1; break; case OP_SCSI_DISPATCH: { // SCSIDispatch() replacement uint32 ret = ReadMacInt32(r->a[7]); uint16 sel = ReadMacInt16(r->a[7] + 4); r->a[7] += 6; // D(bug("SCSIDispatch(%d)\n", sel)); int stack; switch (sel) { case 0: // SCSIReset WriteMacInt16(r->a[7], SCSIReset()); stack = 0; break; case 1: // SCSIGet WriteMacInt16(r->a[7], SCSIGet()); stack = 0; break; case 2: // SCSISelect case 11: // SCSISelAtn WriteMacInt16(r->a[7] + 2, SCSISelect(ReadMacInt8(r->a[7] + 1))); stack = 2; break; case 3: // SCSICmd WriteMacInt16(r->a[7] + 6, SCSICmd(ReadMacInt16(r->a[7]), Mac2HostAddr(ReadMacInt32(r->a[7] + 2)))); stack = 6; break; case 4: // SCSIComplete WriteMacInt16(r->a[7] + 12, SCSIComplete(ReadMacInt32(r->a[7]), ReadMacInt32(r->a[7] + 4), ReadMacInt32(r->a[7] + 8))); stack = 12; break; case 5: // SCSIRead case 8: // SCSIRBlind WriteMacInt16(r->a[7] + 4, SCSIRead(ReadMacInt32(r->a[7]))); stack = 4; break; case 6: // SCSIWrite case 9: // SCSIWBlind WriteMacInt16(r->a[7] + 4, SCSIWrite(ReadMacInt32(r->a[7]))); stack = 4; break; case 10: // SCSIStat WriteMacInt16(r->a[7], SCSIStat()); stack = 0; break; case 12: // SCSIMsgIn WriteMacInt16(r->a[7] + 4, 0); stack = 4; break; case 13: // SCSIMsgOut WriteMacInt16(r->a[7] + 2, 0); stack = 2; break; case 14: // SCSIMgrBusy WriteMacInt16(r->a[7], SCSIMgrBusy()); stack = 0; break; default: printf("FATAL: SCSIDispatch: illegal selector\n"); stack = 0; //!! SysError(12) } r->a[0] = ret; r->a[7] += stack; break; } case OP_SCSI_ATOMIC: // SCSIAtomic() replacement D(bug("SCSIAtomic\n")); r->d[0] = (uint32)-7887; break; case OP_CHECK_SYSV: { // Check we are not using MacOS < 8.1 with a NewWorld ROM r->a[1] = r->d[1]; r->a[0] = ReadMacInt32(r->d[1]); uint32 sysv = ReadMacInt16(r->a[0]); D(bug("Detected MacOS version %d.%d.%d\n", (sysv >> 8) & 0xf, (sysv >> 4) & 0xf, sysv & 0xf)); if (ROMType == ROMTYPE_NEWWORLD && sysv < 0x0801) r->d[1] = 0; break; } case OP_NTRB_17_PATCH: r->a[2] = ReadMacInt32(r->a[7]); r->a[7] += 4; if (ReadMacInt16(r->a[2] + 6) == 17) PatchNativeResourceManager(); break; case OP_NTRB_17_PATCH2: r->a[7] += 8; PatchNativeResourceManager(); break; case OP_NTRB_17_PATCH3: r->a[2] = ReadMacInt32(r->a[7]); r->a[7] += 4; D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6))); if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17) PatchNativeResourceManager(); break; case OP_NTRB_17_PATCH4: r->d[0] = ReadMacInt16(r->a[7]); r->a[7] += 2; D(bug("%d %d\n", ReadMacInt16(r->a[2]), ReadMacInt16(r->a[2] + 6))); if (ReadMacInt16(r->a[2]) == 11 && ReadMacInt16(r->a[2] + 6) == 17) PatchNativeResourceManager(); break; case OP_CHECKLOAD: { // vCheckLoad() patch uint32 type = ReadMacInt32(r->a[7]); r->a[7] += 4; int16 id = ReadMacInt16(r->a[2]); if (r->a[0] == 0) break; uint32 adr = ReadMacInt32(r->a[0]); if (adr == 0) break; uint16 *p = (uint16 *)Mac2HostAddr(adr); uint32 size = ReadMacInt32(adr - 8) & 0xffffff; CheckLoad(type, id, p, size); break; } case OP_EXTFS_COMM: // External file system routines WriteMacInt16(r->a[7] + 14, ExtFSComm(ReadMacInt16(r->a[7] + 12), ReadMacInt32(r->a[7] + 8), ReadMacInt32(r->a[7] + 4))); break; case OP_EXTFS_HFS: 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))); break; case OP_IDLE_TIME: // Sleep if no events pending if (ReadMacInt32(0x14c) == 0) idle_wait(); r->a[0] = ReadMacInt32(0x2b6); break; case OP_IDLE_TIME_2: // Sleep if no events pending if (ReadMacInt32(0x14c) == 0) idle_wait(); r->d[0] = (uint32)-2; break; default: printf("FATAL: EMUL_OP called with bogus selector %08x\n", selector); QuitEmulator(); break; } }