From 8b9eb9f5f893cf92a556ffcdc6611e864d649033 Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 7 Sep 2004 18:18:02 +0000 Subject: [PATCH] Files needed for linux to compile properly. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@156 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/snd_linux.c | 310 ++++++++++++++++++++ engine/client/sys_dosa.s | 95 +++++++ engine/client/sys_linux.c | 581 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 986 insertions(+) create mode 100644 engine/client/snd_linux.c create mode 100644 engine/client/sys_dosa.s create mode 100644 engine/client/sys_linux.c diff --git a/engine/client/snd_linux.c b/engine/client/snd_linux.c new file mode 100644 index 000000000..afa8e6c8d --- /dev/null +++ b/engine/client/snd_linux.c @@ -0,0 +1,310 @@ +#ifdef __CYGWIN__ +#include "quakedef.h" +int SNDDMA_Init(soundcardinfo_t *sc) +{ + Con_Printf("Cygwin targets do not have sound. Sorry.\n"); + return 0; +} +void S_Init(void) +{ + Con_Printf("Cygwin targets do not have sound. Sorry.\n"); +} +void S_Startup (void){} +void S_Restart_f (void){} +void SNDDMA_SetUnderWater(qboolean underwater) {} +void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, int width){} +void S_Shutdown (void){} +void S_ShutdownCur (void){} +void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation){} +void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation){} +void S_StopSound (int entnum, int entchannel){} +void S_StopAllSounds(qboolean clear){} +void S_ClearBuffer (soundcardinfo_t *sc){} +void S_Update (vec3_t origin, vec3_t v_forward, vec3_t v_right, vec3_t v_up){} +void S_ExtraUpdate (void){} +sfx_t *S_PrecacheSound (char *sample) +{ + return NULL; +} +void S_TouchSound (char *sample){} +void S_LocalSound (char *s){} +void S_ClearPrecache (void){} +void S_BeginPrecaching (void){} +void S_EndPrecaching (void){} + +cvar_t bgmvolume; +cvar_t volume; +cvar_t precache; + +int snd_speed; +#else + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "quakedef.h" + +qboolean snd_firsttime = true; +static int tryrates[] = { 11025, 22051, 44100, 8000 }; + +soundcardinfo_t *sndcardinfo; + +void SNDDMA_SetUnderWater(qboolean underwater) //simply a stub. Any ideas how to actually implement this properly? +{ +} + +void S_UpdateCapture(void) //any ideas how to get microphone input? +{ +} + +int SNDDMA_Init(soundcardinfo_t *sc) +{ //FIXME: implement snd_multipledevices somehow. + int rc; + int fmt; + int tmp; + int i; + char *s; + struct audio_buf_info info; + int caps; + char *snddev = NULL; + cvar_t *devname; + + soundcardinfo_t *ec; + + devname = Cvar_Get("snd_devicename", "/dev/dsp", 0, "Sound controls"); + snddev = devname->string; + + for (ec = sndcardinfo; ec; ec = ec->next) + if (!strcmp(ec->name, snddev)) + return 2; + +// open the sound device, confirm capability to mmap, and get size of dma buffer + + Q_strncpyz(sc->name, snddev, sizeof(sc->name)); + printf("Initing sound device %s\n", snddev); + + sc->audio_fd = open(snddev, O_RDWR); + if (sc->audio_fd < 0) + { + perror(snddev); + Con_Printf("Could not open %s\n", snddev); + SNDDMA_Shutdown(sc); + return 0; + } + + rc = ioctl(sc->audio_fd, SNDCTL_DSP_RESET, 0); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not reset %s\n", snddev); + SNDDMA_Shutdown(sc); + return 0; + } + + if (ioctl(sc->audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1) + { + perror(snddev); + Con_Printf("Sound driver too old\n"); + SNDDMA_Shutdown(sc); + return 0; + } + + if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) + { + Con_Printf("Sorry but your soundcard can't do this\n"); + SNDDMA_Shutdown(sc); + return 0; + } + + if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) + { + perror("GETOSPACE"); + Con_Printf("Um, can't do GETOSPACE?\n"); + SNDDMA_Shutdown(sc); + return 0; + } + + sc->sn.splitbuffer = 0; + +// set sample bits & speed + + s = getenv("QUAKE_SOUND_SAMPLEBITS"); + if (s) sc->sn.samplebits = atoi(s); + else if ((i = COM_CheckParm("-sndbits")) != 0) + sc->sn.samplebits = atoi(com_argv[i+1]); + if (sc->sn.samplebits != 16 && sc->sn.samplebits != 8) + { + ioctl(sc->audio_fd, SNDCTL_DSP_GETFMTS, &fmt); + if (fmt & AFMT_S16_LE) + sc->sn.samplebits = 16; + else if (fmt & AFMT_U8) + sc->sn.samplebits = 8; + } + + s = getenv("QUAKE_SOUND_SPEED"); + if (s) sc->sn.speed = atoi(s); + else if ((i = COM_CheckParm("-sndspeed")) != 0) + sc->sn.speed = atoi(com_argv[i+1]); + else + { + if (!sc->sn.speed || ioctl(sc->audio_fd, SNDCTL_DSP_SPEED, &sc->sn.speed)) //use the default - menu set value. + { //humph, default didn't work. Go for random preset ones that should work. + for (i=0 ; iaudio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break; + sc->sn.speed = tryrates[i]; + } + } + + s = getenv("QUAKE_SOUND_CHANNELS"); + if (s) sc->sn.numchannels = atoi(s); + else if ((i = COM_CheckParm("-sndmono")) != 0) + sc->sn.numchannels = 1; + else if ((i = COM_CheckParm("-sndstereo")) != 0) + sc->sn.numchannels = 2; + else sc->sn.numchannels = 2; + + sc->sn.samples = info.fragstotal * info.fragsize / (sc->sn.samplebits/8); + sc->sn.submission_chunk = 1; + +// memory map the dma buffer + + sc->sn.buffer = (unsigned char *) mmap(NULL, info.fragstotal + * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, sc->audio_fd, 0); + if (!sc->sn.buffer) + { + perror(snddev); + Con_Printf("Could not mmap %s\n", snddev); + SNDDMA_Shutdown(sc); + return 0; + } + + tmp = 0; + if (sc->sn.numchannels == 2) + tmp = 1; + rc = ioctl(sc->audio_fd, SNDCTL_DSP_STEREO, &tmp); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not set %s to stereo=%d", snddev, sc->sn.numchannels); + SNDDMA_Shutdown(sc); + return 0; + } + if (tmp) + sc->sn.numchannels = 2; + else + sc->sn.numchannels = 1; + + rc = ioctl(sc->audio_fd, SNDCTL_DSP_SPEED, &sc->sn.speed); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not set %s speed to %d", snddev, sc->sn.speed); + SNDDMA_Shutdown(sc); + return 0; + } + + if (sc->sn.samplebits == 16) + { + rc = AFMT_S16_LE; + rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETFMT, &rc); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not support 16-bit data. Try 8-bit.\n"); + SNDDMA_Shutdown(sc); + return 0; + } + } + else if (sc->sn.samplebits == 8) + { + rc = AFMT_U8; + rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETFMT, &rc); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not support 8-bit data.\n"); + SNDDMA_Shutdown(sc); + return 0; + } + } + else + { + perror(snddev); + Con_Printf("%d-bit sound not supported.", sc->sn.samplebits); + SNDDMA_Shutdown(sc); + return 0; + } + +// toggle the trigger & start her up + + tmp = 0; + rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not toggle.\n"); + SNDDMA_Shutdown(sc); + return 0; + } + tmp = PCM_ENABLE_OUTPUT; + rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); + if (rc < 0) + { + perror(snddev); + Con_Printf("Could not toggle.\n"); + SNDDMA_Shutdown(sc); + return 0; + } + + sc->sn.samplepos = 0; + + return 1; +} + +int SNDDMA_GetDMAPos(soundcardinfo_t *sc) +{ + struct count_info count; + + if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) + { + perror("/dev/dsp"); + Con_Printf("Uh, sound dead.\n"); + close(sc->audio_fd); + return 0; + } +// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1); +// fprintf(stderr, "%d \r", count.ptr); + sc->sn.samplepos = count.ptr / (sc->sn.samplebits / 8); + + return sc->sn.samplepos; + +} + +void SNDDMA_Shutdown(soundcardinfo_t *sc) +{ + if (sc->sn.buffer) //close it properly, so we can go and restart it later. + munmap(sc->sn.buffer, sc->sn.samples * (sc->sn.samplebits/8)); + if (sc->audio_fd) + close(sc->audio_fd); + *sc->name = '\0'; +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit(soundcardinfo_t *sc) +{ +} + +#endif diff --git a/engine/client/sys_dosa.s b/engine/client/sys_dosa.s new file mode 100644 index 000000000..7b0ea6189 --- /dev/null +++ b/engine/client/sys_dosa.s @@ -0,0 +1,95 @@ +// +// sys_dosa.s +// x86 assembly-language DOS-dependent routines. + +#include "asm_i386.h" +#include "quakeasm.h" + + + .data + + .align 4 +fpenv: + .long 0, 0, 0, 0, 0, 0, 0, 0 + + .text + +.globl C(MaskExceptions) +C(MaskExceptions): + fnstenv fpenv + orl $0x3F,fpenv + fldenv fpenv + + ret + +#if 0 +.globl C(unmaskexceptions) +C(unmaskexceptions): + fnstenv fpenv + andl $0xFFFFFFE0,fpenv + fldenv fpenv + + ret +#endif + + .data + + .align 4 +.globl ceil_cw, single_cw, full_cw, cw, pushed_cw +ceil_cw: .long 0 +single_cw: .long 0 +full_cw: .long 0 +cw: .long 0 +pushed_cw: .long 0 + + .text + +.globl C(Sys_LowFPPrecision) +C(Sys_LowFPPrecision): + fldcw single_cw + + ret + +.globl C(Sys_HighFPPrecision) +C(Sys_HighFPPrecision): + fldcw full_cw + + ret + +.globl C(Sys_PushFPCW_SetHigh) +C(Sys_PushFPCW_SetHigh): + fnstcw pushed_cw + fldcw full_cw + + ret + +.globl C(Sys_PopFPCW) +C(Sys_PopFPCW): + fldcw pushed_cw + + ret + +.globl C(Sys_SetFPCW) +C(Sys_SetFPCW): + fnstcw cw + movl cw,%eax +#if id386 + andb $0xF0,%ah + orb $0x03,%ah // round mode, 64-bit precision +#endif + movl %eax,full_cw + +#if id386 + andb $0xF0,%ah + orb $0x0C,%ah // chop mode, single precision +#endif + movl %eax,single_cw + +#if id386 + andb $0xF0,%ah + orb $0x08,%ah // ceil mode, single precision +#endif + movl %eax,ceil_cw + + ret + diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c new file mode 100644 index 000000000..75c1872b6 --- /dev/null +++ b/engine/client/sys_linux.c @@ -0,0 +1,581 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +//well, linux or cygwin (windows with posix emulation layer), anyway... + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __CYGWIN__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "quakedef.h" + +#undef malloc + +int noconinput = 0; +int nostdout = 0; + +char *basedir = "."; +char *cachedir = "/tmp"; + +cvar_t sys_linerefresh = {"sys_linerefresh","0"};// set for entity display + + +qboolean Sys_InitTerminal (void) //we either have one or we don't. +{ + return true; +} +void Sys_CloseTerminal (void) +{ +} + + + +qboolean isDedicated; +// ======================================================================= +// General routines +// ======================================================================= + +void Sys_DebugNumber(int y, int val) +{ +} + +/* +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[1024]; + + va_start (argptr,fmt); + _vsnprintf (text,sizeof(text)-1, fmt,argptr); + va_end (argptr); + fprintf(stderr, "%s", text); + + Con_Print (text); +} + +void Sys_Printf (char *fmt, ...) +{ + + va_list argptr; + char text[1024], *t_p; + int l, r; + + if (nostdout) + return; + + va_start (argptr,fmt); + _vsnprintf (text,sizeof(text)-1, fmt,argptr); + va_end (argptr); + + l = strlen(text); + t_p = text; + +// make sure everything goes through, even though we are non-blocking + while (l) + { + r = write (1, text, l); + if (r != l) + sleep (0); + if (r > 0) + { + t_p += r; + l -= r; + } + } + +} +*/ + +void Sys_Printf (char *fmt, ...) +{ + va_list argptr; + char text[2048]; + unsigned char *p; + + va_start (argptr,fmt); + _vsnprintf (text,sizeof(text)-1, fmt,argptr); + va_end (argptr); + + if (strlen(text) > sizeof(text)) + Sys_Error("memory overwrite in Sys_Printf"); + + if (nostdout) + return; + + for (p = (unsigned char *)text; *p; p++) + if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9) + printf("[%02x]", *p); + else + putc(*p, stdout); +} + +void Sys_Quit (void) +{ + Host_Shutdown(); + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + exit(0); +} + +void Sys_Init(void) +{ +#if id386 + Sys_SetFPCW(); +#endif +} + +void Sys_Error (const char *error, ...) +{ + va_list argptr; + char string[1024]; + +// change stdin to non blocking + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); + + va_start (argptr,error); + _vsnprintf (string,sizeof(string)-1, error,argptr); + va_end (argptr); + fprintf(stderr, "Error: %s\n", string); + + *(int*)NULL = 0; + + + Host_Shutdown (); + exit (1); + +} + +void Sys_Warn (char *warning, ...) +{ + va_list argptr; + char string[1024]; + + va_start (argptr,warning); + _vsnprintf (string,sizeof(string)-1, warning,argptr); + va_end (argptr); + fprintf(stderr, "Warning: %s", string); +} + +/* +============ +Sys_FileTime + +returns -1 if not present +============ +*/ +int Sys_FileTime (char *path) +{ + struct stat buf; + + if (stat (path,&buf) == -1) + return -1; + + return buf.st_mtime; +} + + +void Sys_mkdir (char *path) +{ + mkdir (path, 0777); +} +qboolean Sys_remove (char *path) +{ + return system(va("rm \"%s\"", path)); +} + +int Sys_FileOpenRead (char *path, int *handle) +{ + int h; + struct stat fileinfo; + + + h = open (path, O_RDONLY, 0666); + *handle = h; + if (h == -1) + return -1; + + if (fstat (h,&fileinfo) == -1) + Sys_Error ("Error fstating %s", path); + + return fileinfo.st_size; +} + +int Sys_FileOpenWrite (char *path) +{ + int handle; + + umask (0); + + handle = open(path,O_RDWR | O_CREAT | O_TRUNC + , 0666); + + if (handle == -1) + Sys_Error ("Error opening %s: %s", path,strerror(errno)); + + return handle; +} + +int Sys_FileWrite (int handle, void *src, int count) +{ + return write (handle, src, count); +} + +void Sys_FileClose (int handle) +{ + close (handle); +} + +void Sys_FileSeek (int handle, int position) +{ + lseek (handle, position, SEEK_SET); +} + +int Sys_FileRead (int handle, void *dest, int count) +{ + return read (handle, dest, count); +} + +void Sys_DebugLog(char *file, char *fmt, ...) +{ + va_list argptr; + static char data[1024]; + int fd; + + va_start(argptr, fmt); + _vsnprintf (data,sizeof(data)-1, fmt, argptr); + va_end(argptr); + + if (strlen(data) > sizeof(data)) + Sys_Error("Sys_DebugLog's buffer was stomped\n"); +// fd = open(file, O_WRONLY | O_BINARY | O_CREAT | O_APPEND, 0666); + fd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0666); + write(fd, data, strlen(data)); + close(fd); +} + +void Sys_EditFile(char *filename) +{ + + char cmd[256]; + char *term; + char *editor; + + term = getenv("TERM"); + if (term && !strcmp(term, "xterm")) + { + editor = getenv("VISUAL"); + if (!editor) + editor = getenv("EDITOR"); + if (!editor) + editor = getenv("EDIT"); + if (!editor) + editor = "vi"; + sprintf(cmd, "xterm -e %s %s", editor, filename); + system(cmd); + } + +} +//1 if match +//FIXME: make windows like - *.* becomes * +int wildcmp(char *wild, char *string) { + char *cp, *mp; + + while ((*string) && (*wild != '*')) { + if ((*wild != *string) && (*wild != '?')) { + return 0; + } + wild++; + string++; + } + + while (*string) { + if (*wild == '*') { + if (!*++wild) { + return 1; + } + mp = wild; + cp = string+1; + } else if ((*wild == *string) || (*wild == '?')) { + wild++; + string++; + } else { + wild = mp; + string = cp++; + } + } + + while (*wild == '*') { + wild++; + } + return !*wild; +} + + +int Sys_EnumerateFiles (char *gpath, char *match, int (*func)(char *, int, void *), void *parm) +{ +#include + DIR *dir, *dir2; + char apath[MAX_OSPATH]; + char file[MAX_OSPATH]; + char truepath[MAX_OSPATH]; + char *s; + struct dirent *ent; + +//printf("path = %s\n", gpath); +//printf("match = %s\n", match); + + if (!gpath) + gpath = ""; + *apath = '\0'; + + Q_strncpyz(apath, match, sizeof(apath)); + for (s = apath+strlen(apath)-1; s >= apath; s--) + { + if (*s == '/') + { + s[1] = '\0'; + match += s - apath+1; + break; + } + } + if (s < apath) //didn't find a '/' + *apath = '\0'; + + sprintf(truepath, "%s/%s", gpath, apath); + + +//printf("truepath = %s\n", truepath); +//printf("gamepath = %s\n", gpath); +//printf("apppath = %s\n", apath); +//printf("match = %s\n", match); + dir = opendir(truepath); + if (!dir) + { + Con_Printf("Failed to open dir"); + return true; + } + do + { + ent = readdir(dir); + if (!ent) + break; + if (*ent->d_name != '.') + if (wildcmp(match, ent->d_name)) + { + snprintf(file, sizeof(file)-1, "%s/%s", gpath, ent->d_name); +//would use stat, but it breaks on fat32. + + if ((dir2 = opendir(file))) + { + closedir(dir2); + snprintf(file, sizeof(file)-1, "%s%s/", apath, ent->d_name); +//printf("is directory = %s\n", file); + } + else + { + snprintf(file, sizeof(file)-1, "%s%s", apath, ent->d_name); +//printf("file = %s\n", file); + } + + if (!func(file, -2, parm)) + { + closedir(dir); + return false; + } + } + } while(1); + closedir(dir); + + return true; +} + +double Sys_DoubleTime (void) +{ + struct timeval tp; + struct timezone tzp; + static int secbase; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000000.0; + } + + return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0; +} + + +void Sys_UnloadGame (void) +{ +} +void *Sys_GetGameAPI (void *parms) +{ + return NULL; +} + +// ======================================================================= +// Sleeps for microseconds +// ======================================================================= + +static volatile int oktogo; + +void alarm_handler(int x) +{ + oktogo=1; +} + +void Sys_LineRefresh(void) +{ +} + +void floating_point_exception_handler(int whatever) +{ +// Sys_Warn("floating point exception\n"); + signal(SIGFPE, floating_point_exception_handler); +} + +char *Sys_ConsoleInput(void) +{ +#if 0 + static char text[256]; + int len; + + if (cls.state == ca_dedicated) { + len = read (0, text, sizeof(text)); + if (len < 1) + return NULL; + text[len-1] = 0; // rip off the /n and terminate + + return text; + } +#endif + return NULL; +} + +#if !id386 +void Sys_HighFPPrecision (void) +{ +} + +void Sys_LowFPPrecision (void) +{ +} +#endif + +int skipframes; + +int main (int c, char **v) +{ + + double time, oldtime, newtime; + quakeparms_t parms; + int j; + +// static char cwd[1024]; + +// signal(SIGFPE, floating_point_exception_handler); + signal(SIGFPE, SIG_IGN); + + memset(&parms, 0, sizeof(parms)); + + COM_InitArgv(c, v); + TL_InitLanguages(); + parms.argc = com_argc; + parms.argv = com_argv; + + parms.memsize = 16*1024*1024; + + j = COM_CheckParm("-mem"); + if (j) + parms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024); + parms.membase = malloc (parms.memsize); + + parms.basedir = basedir; +// caching is disabled by default, use -cachedir to enable +// parms.cachedir = cachedir; + + noconinput = COM_CheckParm("-noconinput"); + if (!noconinput) + fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); + + if (COM_CheckParm("-nostdout")) + nostdout = 1; + + Sys_Init(); + + Host_Init(&parms); + + oldtime = Sys_DoubleTime (); + while (1) + { +// find time spent rendering last frame + newtime = Sys_DoubleTime (); + time = newtime - oldtime; + + Host_Frame(time); + oldtime = newtime; + } + +} + + +/* +================ +Sys_MakeCodeWriteable +================ +*/ +void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) +{ + + int r; + unsigned long addr; + int psize = getpagesize(); + + addr = (startaddr & ~(psize-1)) - psize; + +// fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, +// addr, startaddr+length, length); + + r = mprotect((char*)addr, length + startaddr - addr + psize, 7); + + if (r < 0) + Sys_Error("Protection change failed\n"); + +} +