1 |
|
/* |
2 |
|
* main_unix.cpp - Emulation core, Unix implementation |
3 |
|
* |
4 |
< |
* SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig |
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 |
110 |
|
#include "vm_alloc.h" |
111 |
|
#include "sigsegv.h" |
112 |
|
#include "sigregs.h" |
113 |
+ |
#include "rpc.h" |
114 |
|
|
115 |
|
#define DEBUG 0 |
116 |
|
#include "debug.h" |
225 |
|
#else |
226 |
|
static struct sigaction sigsegv_action; // Data access exception signal (of emulator thread) |
227 |
|
static struct sigaction sigill_action; // Illegal instruction signal (of emulator thread) |
228 |
< |
static struct sigaltstack sig_stack; // Stack for signal handlers |
229 |
< |
static struct sigaltstack extra_stack; // Stack for SIGSEGV inside interrupt handler |
228 |
> |
static stack_t sig_stack; // Stack for signal handlers |
229 |
> |
static stack_t extra_stack; // Stack for SIGSEGV inside interrupt handler |
230 |
|
static bool emul_thread_fatal = false; // Flag: MacOS thread crashed, tick thread shall dump debug output |
231 |
|
static sigregs sigsegv_regs; // Register dump when crashed |
232 |
|
static const char *crash_reason = NULL; // Reason of the crash (SIGSEGV, SIGBUS, SIGILL) |
233 |
|
#endif |
234 |
|
|
235 |
+ |
static rpc_connection_t *gui_connection = NULL; // RPC connection to the GUI |
236 |
+ |
static const char *gui_connection_path = NULL; // GUI connection identifier |
237 |
+ |
|
238 |
|
uint32 SheepMem::page_size; // Size of a native page |
239 |
|
uintptr SheepMem::zero_page = 0; // Address of ro page filled in with zeros |
240 |
|
uintptr SheepMem::base = 0x60000000; // Address of SheepShaver data |
253 |
|
extern void emul_ppc(uint32 start); |
254 |
|
extern void init_emul_ppc(void); |
255 |
|
extern void exit_emul_ppc(void); |
256 |
< |
sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t); |
256 |
> |
sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip); |
257 |
|
#else |
258 |
|
extern "C" void sigusr2_handler_init(int sig, siginfo_t *sip, void *scp); |
259 |
|
extern "C" void sigusr2_handler(int sig, siginfo_t *sip, void *scp); |
369 |
|
uint32 rom_size, actual; |
370 |
|
uint8 *rom_tmp; |
371 |
|
time_t now, expire; |
372 |
+ |
bool memory_mapped_from_zero; |
373 |
+ |
|
374 |
+ |
#ifdef USE_SDL_VIDEO |
375 |
+ |
// Don't let SDL block the screensaver |
376 |
+ |
putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1"); |
377 |
+ |
|
378 |
+ |
// Make SDL pass through command-clicks and option-clicks unaltered |
379 |
+ |
putenv("SDL_HAS3BUTTONMOUSE=1"); |
380 |
+ |
#endif |
381 |
|
|
382 |
|
// Initialize variables |
383 |
|
RAMBase = 0; |
398 |
|
#endif |
399 |
|
#endif |
400 |
|
|
388 |
– |
#ifdef ENABLE_GTK |
389 |
– |
// Init GTK |
390 |
– |
gtk_set_locale(); |
391 |
– |
gtk_init(&argc, &argv); |
392 |
– |
#endif |
393 |
– |
|
394 |
– |
// Read preferences |
395 |
– |
PrefsInit(argc, argv); |
396 |
– |
|
401 |
|
// Parse command line arguments |
402 |
|
for (int i=1; i<argc; i++) { |
403 |
|
if (strcmp(argv[i], "--help") == 0) { |
408 |
|
if (i < argc) |
409 |
|
x_display_name = strdup(argv[i]); |
410 |
|
#endif |
411 |
< |
} else if (argv[i][0] == '-') { |
411 |
> |
} else if (strcmp(argv[i], "--gui-connection") == 0) { |
412 |
> |
argv[i++] = NULL; |
413 |
> |
if (i < argc) { |
414 |
> |
gui_connection_path = argv[i]; |
415 |
> |
argv[i] = NULL; |
416 |
> |
} |
417 |
> |
} |
418 |
> |
} |
419 |
> |
|
420 |
> |
// Remove processed arguments |
421 |
> |
for (int i=1; i<argc; i++) { |
422 |
> |
int k; |
423 |
> |
for (k=i; k<argc; k++) |
424 |
> |
if (argv[k] != NULL) |
425 |
> |
break; |
426 |
> |
if (k > i) { |
427 |
> |
k -= i; |
428 |
> |
for (int j=i+k; j<argc; j++) |
429 |
> |
argv[j-k] = argv[j]; |
430 |
> |
argc -= k; |
431 |
> |
} |
432 |
> |
} |
433 |
> |
|
434 |
> |
// Connect to the external GUI |
435 |
> |
if (gui_connection_path) { |
436 |
> |
if ((gui_connection = rpc_init_client(gui_connection_path)) == NULL) { |
437 |
> |
fprintf(stderr, "Failed to initialize RPC client connection to the GUI\n"); |
438 |
> |
return 1; |
439 |
> |
} |
440 |
> |
} |
441 |
> |
|
442 |
> |
#ifdef ENABLE_GTK |
443 |
> |
if (!gui_connection) { |
444 |
> |
// Init GTK |
445 |
> |
gtk_set_locale(); |
446 |
> |
gtk_init(&argc, &argv); |
447 |
> |
} |
448 |
> |
#endif |
449 |
> |
|
450 |
> |
// Read preferences |
451 |
> |
PrefsInit(argc, argv); |
452 |
> |
|
453 |
> |
// Any command line arguments left? |
454 |
> |
for (int i=1; i<argc; i++) { |
455 |
> |
if (argv[i][0] == '-') { |
456 |
|
fprintf(stderr, "Unrecognized option '%s'\n", argv[i]); |
457 |
|
usage(argv[0]); |
458 |
|
} |
475 |
|
goto quit; |
476 |
|
} |
477 |
|
atexit(SDL_Quit); |
478 |
+ |
|
479 |
+ |
// Don't let SDL catch SIGINT and SIGTERM signals |
480 |
+ |
signal(SIGINT, SIG_DFL); |
481 |
+ |
signal(SIGTERM, SIG_DFL); |
482 |
|
#endif |
483 |
|
|
484 |
|
#ifndef USE_SDL_VIDEO |
537 |
|
sigsegv_action.sa_restorer = NULL; |
538 |
|
#endif |
539 |
|
if (sigaction(SIGSEGV, &sigsegv_action, NULL) < 0) { |
540 |
< |
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno)); |
540 |
> |
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno)); |
541 |
|
ErrorAlert(str); |
542 |
|
goto quit; |
543 |
|
} |
544 |
|
if (sigaction(SIGBUS, &sigsegv_action, NULL) < 0) { |
545 |
< |
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno)); |
545 |
> |
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGBUS", strerror(errno)); |
546 |
|
ErrorAlert(str); |
547 |
|
goto quit; |
548 |
|
} |
549 |
|
#else |
550 |
|
// Install SIGSEGV handler for CPU emulator |
551 |
|
if (!sigsegv_install_handler(sigsegv_handler)) { |
552 |
< |
sprintf(str, GetString(STR_SIGSEGV_INSTALL_ERR), strerror(errno)); |
552 |
> |
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGSEGV", strerror(errno)); |
553 |
|
ErrorAlert(str); |
554 |
|
goto quit; |
555 |
|
} |
641 |
|
{ 0xffff0000, 0x80010000, "7455" }, |
642 |
|
{ 0xffff0000, 0x80020000, "7457" }, |
643 |
|
{ 0xffff0000, 0x80030000, "7447A" }, |
644 |
+ |
{ 0xffff0000, 0x80040000, "7448" }, |
645 |
|
{ 0x7fff0000, 0x00810000, "82xx" }, |
646 |
|
{ 0x7fff0000, 0x00820000, "8280" }, |
647 |
|
{ 0xffff0000, 0x00400000, "Power3 (630)" }, |
650 |
|
{ 0xffff0000, 0x00370000, "S-star" }, |
651 |
|
{ 0xffff0000, 0x00350000, "Power4" }, |
652 |
|
{ 0xffff0000, 0x00390000, "PPC970" }, |
653 |
< |
{ 0xffff0000, 0x003a0000, "POWER5" }, |
653 |
> |
{ 0xffff0000, 0x003c0000, "PPC970FX" }, |
654 |
> |
{ 0xffff0000, 0x003a0000, "POWER5 (gr)" }, |
655 |
> |
{ 0xffff0000, 0x003b0000, "POWER5+ (gs)" }, |
656 |
> |
{ 0xffff0000, 0x003e0000, "POWER6" }, |
657 |
> |
{ 0xffff0000, 0x00700000, "Cell Broadband Engine" }, |
658 |
> |
{ 0x7fff0000, 0x00900000, "PA6T" }, |
659 |
|
{ 0, 0, 0 } |
660 |
|
}; |
661 |
|
|
669 |
|
|
670 |
|
// Parse line |
671 |
|
int i; |
672 |
+ |
float f; |
673 |
|
char value[256]; |
674 |
< |
if (sscanf(line, "cpu : %[0-9A-Za-a]", value) == 1) { |
674 |
> |
if (sscanf(line, "cpu : %[^,]", value) == 1) { |
675 |
|
// Search by name |
676 |
|
const char *cpu_name = NULL; |
677 |
|
for (int i = 0; cpu_specs[i].pvr_mask != 0; i++) { |
686 |
|
else |
687 |
|
printf("Found a PowerPC %s processor\n", cpu_name); |
688 |
|
} |
689 |
< |
if (sscanf(line, "clock : %dMHz", &i) == 1) |
689 |
> |
if (sscanf(line, "clock : %fMHz", &f) == 1) |
690 |
> |
CPUClockSpeed = BusClockSpeed = ((int64)f) * 1000000; |
691 |
> |
else if (sscanf(line, "clock : %dMHz", &i) == 1) |
692 |
|
CPUClockSpeed = BusClockSpeed = i * 1000000; |
693 |
|
} |
694 |
|
fclose(proc_file); |
733 |
|
case 0x8001: // 7455 |
734 |
|
case 0x8002: // 7457 |
735 |
|
case 0x8003: // 7447A |
736 |
+ |
case 0x8004: // 7448 |
737 |
|
case 0x0039: // 970 |
738 |
+ |
case 0x003c: // 970FX |
739 |
|
PVR = 0x000c0000; // 7400 |
740 |
|
break; |
741 |
|
} |
762 |
|
goto quit; |
763 |
|
} |
764 |
|
|
702 |
– |
#ifndef PAGEZERO_HACK |
703 |
– |
// Create Low Memory area (0x0000..0x3000) |
704 |
– |
if (vm_mac_acquire(0, 0x3000) < 0) { |
705 |
– |
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); |
706 |
– |
ErrorAlert(str); |
707 |
– |
goto quit; |
708 |
– |
} |
709 |
– |
lm_area_mapped = true; |
710 |
– |
#endif |
711 |
– |
|
765 |
|
// Create areas for Kernel Data |
766 |
|
if (!kernel_data_init()) |
767 |
|
goto quit; |
824 |
|
WarningAlert(GetString(STR_SMALL_RAM_WARN)); |
825 |
|
RAMSize = 8*1024*1024; |
826 |
|
} |
827 |
< |
|
828 |
< |
if (vm_mac_acquire(RAM_BASE, RAMSize) < 0) { |
829 |
< |
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); |
830 |
< |
ErrorAlert(str); |
831 |
< |
goto quit; |
827 |
> |
memory_mapped_from_zero = false; |
828 |
> |
#if REAL_ADDRESSING && HAVE_LINKER_SCRIPT |
829 |
> |
if (vm_mac_acquire(0, RAMSize) == 0) { |
830 |
> |
D(bug("Could allocate RAM from 0x0000\n")); |
831 |
> |
RAMBase = 0; |
832 |
> |
memory_mapped_from_zero = true; |
833 |
> |
} |
834 |
> |
#endif |
835 |
> |
if (!memory_mapped_from_zero) { |
836 |
> |
#ifndef PAGEZERO_HACK |
837 |
> |
// Create Low Memory area (0x0000..0x3000) |
838 |
> |
if (vm_mac_acquire(0, 0x3000) < 0) { |
839 |
> |
sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno)); |
840 |
> |
ErrorAlert(str); |
841 |
> |
goto quit; |
842 |
> |
} |
843 |
> |
lm_area_mapped = true; |
844 |
> |
#endif |
845 |
> |
if (vm_mac_acquire(RAM_BASE, RAMSize) < 0) { |
846 |
> |
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); |
847 |
> |
ErrorAlert(str); |
848 |
> |
goto quit; |
849 |
> |
} |
850 |
> |
RAMBase = RAM_BASE; |
851 |
|
} |
852 |
< |
RAMBaseHost = Mac2HostAddr(RAM_BASE); |
852 |
> |
RAMBaseHost = Mac2HostAddr(RAMBase); |
853 |
|
#if !EMULATED_PPC |
854 |
|
if (vm_protect(RAMBaseHost, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) { |
855 |
|
sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno)); |
857 |
|
goto quit; |
858 |
|
} |
859 |
|
#endif |
788 |
– |
RAMBase = RAM_BASE; |
860 |
|
ram_area_mapped = true; |
861 |
|
D(bug("RAM area at %p (%08x)\n", RAMBaseHost, RAMBase)); |
862 |
|
|
926 |
|
sigill_action.sa_restorer = NULL; |
927 |
|
#endif |
928 |
|
if (sigaction(SIGILL, &sigill_action, NULL) < 0) { |
929 |
< |
sprintf(str, GetString(STR_SIGILL_INSTALL_ERR), strerror(errno)); |
929 |
> |
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGILL", strerror(errno)); |
930 |
|
ErrorAlert(str); |
931 |
|
goto quit; |
932 |
|
} |
941 |
|
sigusr2_action.sa_restorer = NULL; |
942 |
|
#endif |
943 |
|
if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) { |
944 |
< |
sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno)); |
944 |
> |
sprintf(str, GetString(STR_SIG_INSTALL_ERR), "SIGUSR2", strerror(errno)); |
945 |
|
ErrorAlert(str); |
946 |
|
goto quit; |
947 |
|
} |
1012 |
|
|
1013 |
|
// Delete RAM area |
1014 |
|
if (ram_area_mapped) |
1015 |
< |
vm_mac_release(RAM_BASE, RAMSize); |
1015 |
> |
vm_mac_release(RAMBase, RAMSize); |
1016 |
|
|
1017 |
|
// Delete ROM area |
1018 |
|
if (rom_area_mapped) |
1052 |
|
XCloseDisplay(x_display); |
1053 |
|
#endif |
1054 |
|
|
1055 |
+ |
// Notify GUI we are about to leave |
1056 |
+ |
if (gui_connection) { |
1057 |
+ |
if (rpc_method_invoke(gui_connection, RPC_METHOD_EXIT, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) |
1058 |
+ |
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID); |
1059 |
+ |
} |
1060 |
+ |
|
1061 |
|
exit(0); |
1062 |
|
} |
1063 |
|
|
1066 |
|
* Initialize Kernel Data segments |
1067 |
|
*/ |
1068 |
|
|
992 |
– |
#if defined(__CYGWIN__) |
993 |
– |
#define WIN32_LEAN_AND_MEAN |
994 |
– |
#include <windows.h> |
995 |
– |
|
996 |
– |
static HANDLE kernel_handle; // Shared memory handle for Kernel Data |
997 |
– |
static DWORD allocation_granule; // Minimum size of allocateable are (64K) |
998 |
– |
static DWORD kernel_area_size; // Size of Kernel Data area |
999 |
– |
#endif |
1000 |
– |
|
1069 |
|
static bool kernel_data_init(void) |
1070 |
|
{ |
1071 |
|
char str[256]; |
1072 |
< |
#ifdef _WIN32 |
1073 |
< |
SYSTEM_INFO si; |
1074 |
< |
GetSystemInfo(&si); |
1007 |
< |
allocation_granule = si.dwAllocationGranularity; |
1008 |
< |
kernel_area_size = (KERNEL_AREA_SIZE + allocation_granule - 1) & -allocation_granule; |
1009 |
< |
|
1010 |
< |
char rcs[10]; |
1011 |
< |
LPVOID kernel_addr; |
1012 |
< |
kernel_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, kernel_area_size, NULL); |
1013 |
< |
if (kernel_handle == NULL) { |
1014 |
< |
sprintf(rcs, "%d", GetLastError()); |
1015 |
< |
sprintf(str, GetString(STR_KD_SHMGET_ERR), rcs); |
1016 |
< |
ErrorAlert(str); |
1017 |
< |
return false; |
1018 |
< |
} |
1019 |
< |
kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule); |
1020 |
< |
if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) { |
1021 |
< |
sprintf(rcs, "%d", GetLastError()); |
1022 |
< |
sprintf(str, GetString(STR_KD_SHMAT_ERR), rcs); |
1023 |
< |
ErrorAlert(str); |
1024 |
< |
return false; |
1025 |
< |
} |
1026 |
< |
kernel_addr = (LPVOID)Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule); |
1027 |
< |
if (MapViewOfFileEx(kernel_handle, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kernel_area_size, kernel_addr) != kernel_addr) { |
1028 |
< |
sprintf(rcs, "%d", GetLastError()); |
1029 |
< |
sprintf(str, GetString(STR_KD2_SHMAT_ERR), rcs); |
1030 |
< |
ErrorAlert(str); |
1031 |
< |
return false; |
1032 |
< |
} |
1033 |
< |
#else |
1034 |
< |
kernel_area = shmget(IPC_PRIVATE, KERNEL_AREA_SIZE, 0600); |
1072 |
> |
uint32 kernel_area_size = (KERNEL_AREA_SIZE + SHMLBA - 1) & -SHMLBA; |
1073 |
> |
|
1074 |
> |
kernel_area = shmget(IPC_PRIVATE, kernel_area_size, 0600); |
1075 |
|
if (kernel_area == -1) { |
1076 |
|
sprintf(str, GetString(STR_KD_SHMGET_ERR), strerror(errno)); |
1077 |
|
ErrorAlert(str); |
1078 |
|
return false; |
1079 |
|
} |
1080 |
< |
if (shmat(kernel_area, Mac2HostAddr(KERNEL_DATA_BASE), 0) < 0) { |
1080 |
> |
void *kernel_addr = Mac2HostAddr(KERNEL_DATA_BASE & -SHMLBA); |
1081 |
> |
if (shmat(kernel_area, kernel_addr, 0) != kernel_addr) { |
1082 |
|
sprintf(str, GetString(STR_KD_SHMAT_ERR), strerror(errno)); |
1083 |
|
ErrorAlert(str); |
1084 |
|
return false; |
1085 |
|
} |
1086 |
< |
if (shmat(kernel_area, Mac2HostAddr(KERNEL_DATA2_BASE), 0) < 0) { |
1086 |
> |
kernel_addr = Mac2HostAddr(KERNEL_DATA2_BASE & -SHMLBA); |
1087 |
> |
if (shmat(kernel_area, kernel_addr, 0) != kernel_addr) { |
1088 |
|
sprintf(str, GetString(STR_KD2_SHMAT_ERR), strerror(errno)); |
1089 |
|
ErrorAlert(str); |
1090 |
|
return false; |
1091 |
|
} |
1050 |
– |
#endif |
1092 |
|
return true; |
1093 |
|
} |
1094 |
|
|
1099 |
|
|
1100 |
|
static void kernel_data_exit(void) |
1101 |
|
{ |
1061 |
– |
#ifdef _WIN32 |
1062 |
– |
if (kernel_handle) { |
1063 |
– |
UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA_BASE & -allocation_granule)); |
1064 |
– |
UnmapViewOfFile(Mac2HostAddr(KERNEL_DATA2_BASE & -allocation_granule)); |
1065 |
– |
CloseHandle(kernel_handle); |
1066 |
– |
} |
1067 |
– |
#else |
1102 |
|
if (kernel_area >= 0) { |
1103 |
< |
shmdt(Mac2HostAddr(KERNEL_DATA_BASE)); |
1104 |
< |
shmdt(Mac2HostAddr(KERNEL_DATA2_BASE)); |
1103 |
> |
shmdt(Mac2HostAddr(KERNEL_DATA_BASE & -SHMLBA)); |
1104 |
> |
shmdt(Mac2HostAddr(KERNEL_DATA2_BASE & -SHMLBA)); |
1105 |
|
shmctl(kernel_area, IPC_RMID, NULL); |
1106 |
|
} |
1073 |
– |
#endif |
1107 |
|
} |
1108 |
|
|
1109 |
|
|
1623 |
|
*/ |
1624 |
|
|
1625 |
|
#if !EMULATED_PPC |
1626 |
+ |
// XXX: don't redefine locally? |
1627 |
+ |
// Note: Original declaration is in sigsegv.cpp |
1628 |
+ |
// FIXME: If HAVE_MACH_EXCEPTIONS is set, sigsegv_info_t has a bunch of other |
1629 |
+ |
// fields too! Let's hope Screen_fault_handler() doesn't use them... |
1630 |
+ |
struct sigsegv_info_t { |
1631 |
+ |
sigsegv_address_t addr; |
1632 |
+ |
sigsegv_address_t pc; |
1633 |
+ |
}; |
1634 |
+ |
|
1635 |
|
static void sigsegv_handler(int sig, siginfo_t *sip, void *scp) |
1636 |
|
{ |
1637 |
|
machine_regs *r = MACHINE_REGISTERS(scp); |
1649 |
|
#endif |
1650 |
|
|
1651 |
|
#if ENABLE_VOSF |
1652 |
< |
// Handle screen fault. |
1653 |
< |
extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction); |
1654 |
< |
if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->pc())) |
1652 |
> |
// Handle screen fault |
1653 |
> |
#if SIGSEGV_CHECK_VERSION(1,0,0) |
1654 |
> |
sigsegv_info_t si; |
1655 |
> |
si.addr = (sigsegv_address_t)addr; |
1656 |
> |
si.pc = (sigsegv_address_t)r->pc(); |
1657 |
> |
#endif |
1658 |
> |
extern bool Screen_fault_handler(sigsegv_info_t *sip); |
1659 |
> |
if (Screen_fault_handler(&si)) |
1660 |
|
return; |
1661 |
|
#endif |
1662 |
|
|
2164 |
|
|
2165 |
|
void ErrorAlert(const char *text) |
2166 |
|
{ |
2167 |
+ |
if (gui_connection) { |
2168 |
+ |
if (rpc_method_invoke(gui_connection, RPC_METHOD_ERROR_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR && |
2169 |
+ |
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) |
2170 |
+ |
return; |
2171 |
+ |
} |
2172 |
|
#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) |
2173 |
|
if (PrefsFindBool("nogui") || x_display == NULL) { |
2174 |
|
printf(GetString(STR_SHELL_ERROR_PREFIX), text); |
2188 |
|
|
2189 |
|
void WarningAlert(const char *text) |
2190 |
|
{ |
2191 |
+ |
if (gui_connection) { |
2192 |
+ |
if (rpc_method_invoke(gui_connection, RPC_METHOD_WARNING_ALERT, RPC_TYPE_STRING, text, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR && |
2193 |
+ |
rpc_method_wait_for_reply(gui_connection, RPC_TYPE_INVALID) == RPC_ERROR_NO_ERROR) |
2194 |
+ |
return; |
2195 |
+ |
} |
2196 |
|
#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) |
2197 |
|
if (PrefsFindBool("nogui") || x_display == NULL) { |
2198 |
|
printf(GetString(STR_SHELL_WARNING_PREFIX), text); |