/* ============= RunThreadsOn ============= */ void RunThreadsOn (threadfunc_t func) { pthread_t work_threads[MAX_THREADS]; void *status; pthread_attr_t attrib; long i; if (numthreads <= 1) { func (NULL); return; } if (pthread_attr_init (&attrib) == -1) COM_Error ("pthread_attr_init failed"); if (pthread_attr_setstacksize (&attrib, stacksiz) == -1) COM_Error ("pthread_attr_setstacksize failed"); workfunc = func; for (i = 0; i < numthreads; i++) { if (pthread_create (&work_threads[i], &attrib, ThreadWorkerFunc, (void *)i) == -1) COM_Error ("pthread_create failed"); } for (i = 0; i < numthreads; i++) { if (pthread_join (work_threads[i], &status) == -1) COM_Error ("pthread_join failed"); } }
void InitThreads (int wantthreads, size_t needstack) { pthread_mutexattr_t mattrib; if (needstack != 0) stacksiz = needstack; else stacksiz = DEFAULT_STACKSIZ; numthreads = wantthreads; if (numthreads < 0) numthreads = Thread_GetNumCPUS (); if (numthreads < 1) numthreads = 1; if (numthreads > MAX_THREADS) numthreads = MAX_THREADS; printf ("Setup for %d threads, 0x%x stack size\n", numthreads, (unsigned int)stacksiz); if (numthreads <= 1) return; my_mutex = (pthread_mutex_t *) SafeMalloc (sizeof (*my_mutex)); if (pthread_mutexattr_init (&mattrib) == -1) COM_Error ("pthread_mutex_attr_init failed"); if (pthread_mutex_init (my_mutex, &mattrib) == -1) COM_Error ("pthread_mutex_init failed"); }
/* ============= RunThreadsOn ============= */ void RunThreadsOn (threadfunc_t func) { pid_t pid[MAX_THREADS]; long i; if (numthreads <= 1) { func (NULL); return; } init_lock (&lck); workfunc = func; for (i = 0; i < numthreads - 1; i++) { pid[i] = sprocsp (ThreadWorkerFunc, PR_SALL, (void *)i, NULL, stacksiz); if (pid[i] == -1) { perror ("sproc"); COM_Error ("sproc failed"); } } func ((void *)i); for (i = 0; i < numthreads - 1; i++) wait (NULL); }
/* ============ WriteFiles Generates files.dat, which contains all of the data files actually used by the game, to be processed by qfiles.exe ============ */ static void WriteFiles (void) { FILE *f; int i; char filename[1024]; q_snprintf (filename, sizeof(filename), "%sfiles.dat", sourcedir); f = fopen (filename, "w"); if (!f) COM_Error ("Couldn't open %s", filename); fprintf (f, "%i\n", numsounds); for (i = 0; i < numsounds; i++) fprintf (f, "%i %s\n", precache_sounds_block[i], precache_sounds[i]); fprintf (f, "%i\n", nummodels); for (i = 0; i < nummodels; i++) fprintf (f, "%i %s\n", precache_models_block[i], precache_models[i]); fprintf (f, "%i\n", numfiles); for (i = 0; i < numfiles; i++) fprintf (f, "%i %s\n", precache_files_block[i], precache_files[i]); fclose (f); }
BOOL COM_Write( int item, void *buff, int size ) { BOOL ok=TRUE; DWORD done; if( COM_Handle(item) == INVALID_HANDLE_VALUE ) { COM_errorf("COM_Write(...) Invalid handle.\n"); return(FALSE); } if( !WriteFile(COM_Item[item].comH,buff,size,&done,NULL) ) { COM_errorf("COM_Write(COM%d) WriteFile() Failed (%s).\n",COM_Item[item].comX,COM_Error()); ok = FALSE; } else if( size != (int)done ) { COM_errorf("COM_Write(COM%d) WriteFile() Incomplete (size=%d, done=%ld).\n",COM_Item[item].comX,size,done); ok = FALSE; } return(ok); }
int Q_WriteFileFromHandle (FILE *fromfile, const char *topath, size_t size) { char buf[COPY_READ_BUFSIZE]; FILE *out; /* off_t remaining, count;*/ size_t remaining, count; char temp[1024]; strcpy (temp, topath); CreatePath (temp); out = fopen (topath, "wb"); if (!out) COM_Error ("Unable to create file %s", topath); remaining = size; while (remaining) { if (remaining < sizeof(buf)) count = remaining; else count = sizeof(buf); if (fread(buf, 1, count, fromfile) != count) break; if (fwrite(buf, 1, count, out) != count) break; remaining -= count; } fclose (out); return (remaining == 0)? 0 : 1; }
void Q_mkdir (const char *path) { if (CreateDirectory(path, NULL) != 0) return; if (GetLastError() != ERROR_ALREADY_EXISTS) COM_Error ("Unable to create directory %s", path); }
static void TestSingleLightFace (entity_t *light, lightinfo_t *l, const vec3_t faceoffset) { vec_t dist; vec_t add; vec_t *surf; vec3_t rel; int surf_r; int surf_g; int surf_b; int c; VectorSubtract (light->origin, bsp_origin, rel); dist = scaledDistance((DotProduct(rel, l->facenormal) - l->facedist), light); // don't bother with lights behind the surface if (dist <= 0) return; // don't bother with light too far away if (dist > abs(light->light)) { return; } // mfah - find the light color based on the surface name FindTexlightColor (&surf_r, &surf_g, &surf_b, l->texname); surf = l->surfpt[0]; // we could speed the whole thing up drastically by checking only // the first and last point of each face - trouble is, any large // faces may have a light that only hits the middle. for (c = 0 ; c < l->numsurfpt ; c++, surf+=3) { if (surf > l->surfpt[SINGLEMAP - 1]) COM_Error ("%s: surf out of bounds (numsurfpt=%d)", __thisfunc__, l->numsurfpt); dist = scaledDistance(CastRay(light->origin, surf), light); if (dist < 0) continue; // light doesn't reach add = scaledLight(CastRay(light->origin, surf), light); if (add < (light->light / 3)) continue; // normal light - other lights already have a color assigned // to them from when they were initially loaded // this will give madly high color values here so we will // scale them down later on light->lightcolor[0] = light->lightcolor[0] + surf_r; light->lightcolor[1] = light->lightcolor[1] + surf_g; light->lightcolor[2] = light->lightcolor[2] + surf_b; // speed up the checking process some more - if we have one hit // on a face, all other hits on the same face are just going to // give the same result - so we can return now. return; } }
const char *Q_FindFirstFile (const char *path, const char *pattern) { BPTR newdir; if (apath) COM_Error ("FindFirst without FindClose"); apath = (struct AnchorPath *) AllocVec (sizeof(struct AnchorPath) + PATH_SIZE, MEMF_CLEAR); if (!apath) return NULL; apath->ap_Strlen = PATH_SIZE; apath->ap_BreakBits = 0; apath->ap_Flags = 0; /* APF_DOWILD */ newdir = Lock((const STRPTR) path, SHARED_LOCK); if (newdir) oldcurrentdir = CurrentDir(newdir); else { FreeVec(apath); apath = NULL; return NULL; } pattern_str = pattern_helper (pattern); if (MatchFirst((const STRPTR) pattern_str, apath) == 0) { if (apath->ap_Info.fib_DirEntryType < 0) return (const char *) (apath->ap_Info.fib_FileName); } return Q_FindNextFile(); }
/* =============== RunThreadsOn =============== */ void RunThreadsOn (threadfunc_t func) { unsigned IDThread; HANDLE work_threads[MAX_THREADS]; INT_PTR i; if (numthreads <= 1) { func (NULL); return; } workfunc = func; for (i = 0; i < numthreads; i++) { work_threads[i] = (HANDLE) _beginthreadex(NULL, /* no security attributes */ stacksiz, /* stack size */ ThreadWorkerFunc, /* thread function */ (void *) i, /* thread function arg */ 0, /* run immediately */ &IDThread); if (!work_threads[i]) COM_Error ("_beginthreadex () failed"); } for (i = 0; i < numthreads; i++) { WaitForSingleObject(work_threads[i], INFINITE); } }
/* =============== RunThreadsOn =============== */ void RunThreadsOn (threadfunc_t func) { LONG i; if (numthreads <= 1) { work_threads[0] = -1; func (NULL); return; } workfunc = func; for (i = 0; i < numthreads; i++) { work_threads[i] = _beginthread(ThreadWorkerFunc, NULL, stacksiz, (void *)i); if (work_threads[i] == -1) COM_Error ("_beginthread() failed"); } for (i = 0; i < numthreads; i++) { while (work_threads[i] != -1) DosSleep (100); } }
void Q_mkdir (const char *path) { int rc = mkdir (path, 0777); if (rc != 0 && errno == EEXIST) rc = 0; if (rc != 0) COM_Error ("Unable to create directory %s", path); }
/* ================ CalcFaceExtents Fills in s->texmins[] and s->texsize[] also sets exactmins[] and exactmaxs[] ================ */ static void CalcFaceExtents (lightinfo_t *l, const vec3_t faceoffset, qboolean fail) { dface_t *s; vec_t mins[2], maxs[2], val; int i, j, e; dvertex_t *v; texinfo_t *tex; s = l->face; mins[0] = mins[1] = 999999; maxs[0] = maxs[1] = -99999; tex = &texinfo[s->texinfo]; for (i = 0 ; i < s->numedges ; i++) { e = dsurfedges[s->firstedge+i]; if (e >= 0) v = dvertexes + dedges[e].v[0]; else v = dvertexes + dedges[-e].v[1]; for (j = 0 ; j < 2 ; j++) { val = ((double)v->point[0] + faceoffset[0]) * (double)tex->vecs[j][0] + ((double)v->point[1] + faceoffset[1]) * (double)tex->vecs[j][1] + ((double)v->point[2] + faceoffset[2]) * (double)tex->vecs[j][2] + (double)tex->vecs[j][3]; if (val < mins[j]) mins[j] = val; if (val > maxs[j]) maxs[j] = val; } } for (i = 0 ; i < 2 ; i++) { l->exactmins[i] = mins[i]; l->exactmaxs[i] = maxs[i]; mins[i] = floor(mins[i]/16); maxs[i] = ceil(maxs[i]/16); /* l->texmins[i] = (int)floor(mins[i]); l->texsize[i] = (int)floor(maxs[i] - mins[i]); */ l->texmins[i] = mins[i]; l->texsize[i] = maxs[i] - mins[i]; if (fail && l->texsize[i] > 17) COM_Error ("Bad surface extents"); } }
/* ================ CalcFaceVectors Fills in texorg, worldtotex. and textoworld ================ */ static void CalcFaceVectors (lightinfo_t *l) { texinfo_t *tex; int i, j; vec3_t texnormal; float distscale; vec_t dist, len; tex = &texinfo[l->face->texinfo]; // convert from float to vec_t for (i = 0 ; i < 2 ; i++) { for (j = 0 ; j < 3 ; j++) l->worldtotex[i][j] = tex->vecs[i][j]; } // calculate a normal to the texture axis. points can be moved along this // without changing their S/T texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2] - tex->vecs[1][2]*tex->vecs[0][1]; texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0] - tex->vecs[1][0]*tex->vecs[0][2]; texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1] - tex->vecs[1][1]*tex->vecs[0][0]; VectorNormalize (texnormal); // flip it towards plane normal distscale = DotProduct (texnormal, l->facenormal); if (!distscale) COM_Error ("Texture axis perpendicular to face"); if (distscale < 0) { distscale = -distscale; VectorNegate (texnormal, texnormal); } // distscale is the ratio of the distance along the texture normal to // the distance along the plane normal distscale = 1/distscale; for (i = 0 ; i < 2 ; i++) { len = VectorLength (l->worldtotex[i]); dist = DotProduct (l->worldtotex[i], l->facenormal); dist *= distscale; VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]); VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]); } // calculate texorg on the texture plane for (i = 0 ; i < 3 ; i++) l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i]; // project back to the face plane dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1; dist *= distscale; VectorMA (l->texorg, -dist, texnormal, l->texorg); }
/* ============== SafeOpenRead ============== */ FILE *SafeOpenRead (const char *filename) { FILE *f; f = fopen(filename, "rb"); if (!f) COM_Error("Error opening %s: %s", filename, strerror(errno)); return f; }
void Q_getwd (char *out, size_t size, qboolean trailing_dirsep) { ULONG l, drv; if (size < 8) COM_Error ("Too small buffer for getcwd"); l = size - 3; if (DosQueryCurrentDir(0, (PBYTE) out + 3, &l) != NO_ERROR) COM_Error ("Couldn't determine current directory"); DosQueryCurrentDisk(&drv, &l); out[0] = drv + 'A' - 1; out[1] = ':'; out[2] = '\\'; if (!trailing_dirsep) return; l = strlen(out); if (out[l - 1] == '\\' || out[l - 1] == '/') return; qerr_strlcat(__thisfunc__, __LINE__, out, "\\", size); }
void Q_mkdir (const char *path) { FILESTATUS3 fs; APIRET rc = DosCreateDir(path, NULL); if (rc == NO_ERROR) return; if ((DosQueryPathInfo(path, FIL_STANDARD, &fs, sizeof(fs)) == NO_ERROR) && (fs.attrFile & FILE_DIRECTORY)) { return; /* dir exists */ } COM_Error ("Unable to create directory %s", path); }
BOOL COM_Close( HANDLE comH ) { BOOL ok=TRUE; if( !CloseHandle(comH) ) { COM_errorf("COM_Close(...) CloseHandle() Failed (%s).\n",COM_Error()); ok = FALSE; } return(ok); }
const char *Q_FindFirstFile (const char *path, const char *pattern) { if (findhandle != INVALID_HANDLE_VALUE) COM_Error ("FindFirst without FindClose"); q_snprintf (findstr, sizeof(findstr), "%s/%s", path, pattern); findhandle = FindFirstFile(findstr, &finddata); if (findhandle == INVALID_HANDLE_VALUE) return NULL; if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return Q_FindNextFile(); return finddata.cFileName; }
byte *GetFileSpace (int size) { byte *buf; ThreadLock(); file_p = (byte *)(((intptr_t)file_p + 3) & ~3); buf = file_p; file_p += size; ThreadUnlock(); if (file_p > file_end) COM_Error ("%s: overrun", __thisfunc__); return buf; }
void Q_getwd (char *out, size_t size, qboolean trailing_dirsep) { size_t sz; if (getcwd(out, size) == NULL) COM_Error ("Couldn't determine current directory"); if (!trailing_dirsep) return; sz = strlen(out); if (!sz || out[sz - 1] == '/') return; qerr_strlcat(__thisfunc__, __LINE__, out, "/", size); }
/* ============ Q_CopyFile Used to archive source files ============ */ #define COPY_READ_BUFSIZE 8192 /* BUFSIZ */ int Q_CopyFile (const char *frompath, const char *topath) { char buf[COPY_READ_BUFSIZE]; FILE *in, *out; char temp[1024]; /* off_t remaining, count;*/ size_t remaining, count; strcpy (temp, topath); CreatePath (temp); in = fopen (frompath, "rb"); if (!in) COM_Error ("Unable to open file %s", frompath); out = fopen (topath, "wb"); if (!out) COM_Error ("Unable to create file %s", topath); remaining = Q_filelength (in); while (remaining) { if (remaining < sizeof(buf)) count = remaining; else count = sizeof(buf); if (fread(buf, 1, count, in) != count) break; if (fwrite(buf, 1, count, out) != count) break; remaining -= count; } fclose (in); fclose (out); return (remaining == 0)? 0 : 1; }
const char *Q_FindFirstFile (const char *path, const char *pattern) { if (findhandle == 0) COM_Error ("FindFirst without FindClose"); q_snprintf (findstr, sizeof(findstr), "%s/%s", path, pattern); memset (&finddata, 0, sizeof(finddata)); findhandle = findfirst(findstr, &finddata, FA_ARCH | FA_RDONLY); if (findhandle == 0) return finddata.ff_name; return NULL; }
void Q_mkdir (const char *path) { BPTR lock = CreateDir((const STRPTR) path); if (lock) { UnLock(lock); return; } if (IoErr() == ERROR_OBJECT_EXISTS) return; COM_Error("Unable to create directory %s", path); }
static def_t *PR_DefForFieldOfs (gofs_t ofs) { def_t *d; for (d = pr.def_head.next; d; d = d->next) { if (d->type->type != ev_field) continue; if (((int *)pr_globals)[d->ofs] == ofs) return d; } COM_Error ("%s: couldn't find %i", __thisfunc__, ofs); return NULL; }
void Q_getwd (char *out, size_t size, qboolean trailing_dirsep) { size_t sz; sz = GetCurrentDirectory(size, out); if (sz == 0 || sz > size) COM_Error ("Couldn't determine current directory"); if (!trailing_dirsep) return; sz = strlen(out); if (!sz || out[sz - 1] == '\\' || out[sz - 1] == '/') return; qerr_strlcat(__thisfunc__, __LINE__, out, "\\", size); }
void Q_mkdir (const char *path) { int rc = mkdir (path, 0777); if (rc != 0 && errno == EEXIST) { struct stat st; if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) rc = 0; } if (rc != 0) { rc = errno; COM_Error ("Unable to create directory %s: %s", path, strerror(rc)); } }
int Thread_GetNumCPUS (void) { SYSTEM_INFO info; OSVERSIONINFO vinfo; int numcpus; vinfo.dwOSVersionInfoSize = sizeof(vinfo); if (!GetVersionEx (&vinfo)) COM_Error ("Couldn't get OS info"); if (vinfo.dwMajorVersion < 4 || vinfo.dwPlatformId < VER_PLATFORM_WIN32_NT) return 1; GetSystemInfo(&info); numcpus = info.dwNumberOfProcessors; return (numcpus < 1) ? 1 : numcpus; }
void Q_getwd (char *out, size_t size, qboolean trailing_dirsep) { #if 0 qerr_strlcpy(__thisfunc__, __LINE__, out, "PROGDIR:", size); #else size_t sz; if (NameFromLock(((struct Process *) FindTask(NULL))->pr_CurrentDir, (STRPTR) out, size) == 0) COM_Error ("Couldn't determine current directory"); if (!trailing_dirsep) return; sz = strlen(out); if (!sz || out[sz - 1] == ':' || out[sz - 1] == '/') return; qerr_strlcat(__thisfunc__, __LINE__, out, "/", size); #endif }
void LoadTriangleList(const char *fileName, triangle_t **triList, int *triangleCount) { FILE *input; q_strlcpy(InputFileName, fileName, sizeof(InputFileName)); StripExtension(InputFileName); q_strlcat(InputFileName, ".asc", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { fclose(input); LoadASC(InputFileName, triList, triangleCount); return; } StripExtension(InputFileName); q_strlcat(InputFileName, ".hrc", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { fclose(input); LoadHRC(InputFileName, triList, triangleCount); return; } StripExtension(InputFileName); q_strlcat(InputFileName, ".htr", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { fclose(input); LoadHTR(InputFileName, triList, triangleCount); return; } StripExtension(InputFileName); q_strlcat(InputFileName, ".tri", sizeof(InputFileName)); if ((input = fopen(InputFileName, "rb")) != NULL) { LoadTRI(input, triList, triangleCount); fclose(input); return; } COM_Error("Could not open file '%s':\n" "No ASC, HRC, HTR, or TRI match.\n", fileName); }