int FIWadManager::CheckIWAD (const char *doomwaddir, WadStuff *wads) { const char *slash; int numfound; numfound = 0; slash = (doomwaddir[0] && doomwaddir[strlen (doomwaddir)-1] != '/') ? "/" : ""; // Search for a pre-defined IWAD for (unsigned i=0; i< mIWadNames.Size(); i++) { if (mIWadNames[i].IsNotEmpty() && wads[i].Path.IsEmpty()) { FString iwad; iwad.Format ("%s%s%s", doomwaddir, slash, mIWadNames[i].GetChars()); FixPathSeperator (iwad); if (FileExists (iwad)) { wads[i].Type = ScanIWAD (iwad); if (wads[i].Type != -1) { wads[i].Path = iwad; wads[i].Name = mIWads[wads[i].Type].Name; numfound++; } } } } return numfound; }
/* This is meant to find and open files for reading. */ FileReader *open_filereader(const char *name, int open, int *plumpnum) { FileReader *fp; FString current_filename; if (!name || !(*name)) { return 0; } /* First try the given name */ current_filename = name; FixPathSeperator(current_filename); int lumpnum = Wads.CheckNumForFullName(current_filename); if (open != OM_FILE) { if (lumpnum >= 0) { fp = Wads.ReopenLumpNum(lumpnum); if (plumpnum) *plumpnum = lumpnum; return fp; } if (open == OM_LUMP) // search the path list when not loading the main config { for (unsigned int plp = PathList.Size(); plp-- != 0; ) { /* Try along the path then */ current_filename = BuildPath(PathList[plp], name); lumpnum = Wads.CheckNumForFullName(current_filename); if (lumpnum >= 0) { fp = Wads.ReopenLumpNum(lumpnum); if (plumpnum) *plumpnum = lumpnum; return fp; } } return NULL; } } if (plumpnum) *plumpnum = -1; fp = new FileReader; if (fp->Open(current_filename)) return fp; if (name[0] != '/') { for (unsigned int plp = PathList.Size(); plp-- != 0; ) { /* Try along the path then */ current_filename = BuildPath(PathList[plp], name); if (fp->Open(current_filename)) return fp; } } delete fp; /* Nothing could be opened. */ current_filename = ""; return NULL; }
static int CheckIWAD (const char *doomwaddir, WadStuff *wads) { const char *slash; int i; int numfound; numfound = 0; slash = (doomwaddir[0] && doomwaddir[strlen (doomwaddir)-1] != '/') ? "/" : ""; // Search for a pre-defined IWAD for (i = IWADNames[0] ? 0 : 1; IWADNames[i]; i++) { if (wads[i].Path.IsEmpty()) { FString iwad; iwad.Format ("%s%s%s", doomwaddir, slash, IWADNames[i]); FixPathSeperator (iwad); if (FileExists (iwad)) { wads[i].Type = ScanIWAD (iwad); if (wads[i].Type != NUM_IWAD_TYPES) { wads[i].Path = iwad; numfound++; } } } } return numfound; }
FString FPlayList::NextLine (FILE *file) { char buffer[512]; char *skipper; do { if (NULL == fgets (buffer, countof(buffer), file)) return ""; for (skipper = buffer; *skipper != 0 && *skipper <= ' '; skipper++) ; } while (*skipper == '#' || *skipper == 0); FString str(skipper); str.StripRight("\r\n"); FixPathSeperator(str); return str; }
/* This adds a directory to the path list */ void add_to_pathlist(const char *s) { FString copy = s; FixPathSeperator(copy); PathList.Push(copy); }
bool F7ZFile::Open(bool quiet) { Archive = new C7zArchive(Reader); int skipped = 0; SRes res; res = Archive->Open(); if (res != SZ_OK) { delete Archive; Archive = NULL; if (!quiet) { Printf("\n" TEXTCOLOR_RED "%s: ", Filename); if (res == SZ_ERROR_UNSUPPORTED) { Printf("Decoder does not support this archive\n"); } else if (res == SZ_ERROR_MEM) { Printf("Cannot allocate memory\n"); } else if (res == SZ_ERROR_CRC) { Printf("CRC error\n"); } else { Printf("error #%d\n", res); } } return false; } NumLumps = Archive->DB.db.NumFiles; Lumps = new F7ZLump[NumLumps]; F7ZLump *lump_p = Lumps; TArray<UInt16> nameUTF16; TArray<char> nameASCII; for (DWORD i = 0; i < NumLumps; ++i) { CSzFileItem *file = &Archive->DB.db.Files[i]; // skip Directories if (file->IsDir) { skipped++; continue; } const size_t nameLength = SzArEx_GetFileNameUtf16(&Archive->DB, i, NULL); if (0 == nameLength) { ++skipped; continue; } nameUTF16.Resize(nameLength); nameASCII.Resize(nameLength); SzArEx_GetFileNameUtf16(&Archive->DB, i, &nameUTF16[0]); for (size_t c = 0; c < nameLength; ++c) { nameASCII[c] = static_cast<char>(nameUTF16[c]); } FixPathSeperator(&nameASCII[0]); FString name = &nameASCII[0]; name.ToLower(); lump_p->LumpNameSetup(name); lump_p->LumpSize = int(file->Size); lump_p->Owner = this; lump_p->Flags = LUMPF_ZIPFILE; lump_p->Position = i; lump_p->CheckEmbedded(); lump_p++; } // Resize the lump record array to its actual size NumLumps -= skipped; if (NumLumps > 0) { // Quick check for unsupported compression method TArray<char> temp; temp.Resize(Lumps[0].LumpSize); if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0])) { if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", Filename); return false; } } if (!quiet) Printf(", %d lumps\n", NumLumps); // Entries in archives are sorted alphabetically qsort(&Lumps[0], NumLumps, sizeof(F7ZLump), lumpcmp); return true; }
void DoMain (HINSTANCE hInstance) { LONG WinWidth, WinHeight; int height, width, x, y; RECT cRect; TIMECAPS tc; DEVMODE displaysettings; try { #ifdef _MSC_VER _set_new_handler (NewFailure); #endif Args = new DArgs(__argc, __argv); // Load Win32 modules Kernel32Module.Load({"kernel32.dll"}); Shell32Module.Load({"shell32.dll"}); User32Module.Load({"user32.dll"}); // Under XP, get our session ID so we can know when the user changes/locks sessions. // Since we need to remain binary compatible with older versions of Windows, we // need to extract the ProcessIdToSessionId function from kernel32.dll manually. HMODULE kernel = GetModuleHandle ("kernel32.dll"); if (Args->CheckParm("-stdout")) { // As a GUI application, we don't normally get a console when we start. // If we were run from the shell and are on XP+, we can attach to its // console. Otherwise, we can create a new one. If we already have a // stdout handle, then we have been redirected and should just use that // handle instead of creating a console window. StdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (StdOut != NULL) { // It seems that running from a shell always creates a std output // for us, even if it doesn't go anywhere. (Running from Explorer // does not.) If we can get file information for this handle, it's // a file or pipe, so use it. Otherwise, pretend it wasn't there // and find a console to use instead. BY_HANDLE_FILE_INFORMATION info; if (!GetFileInformationByHandle(StdOut, &info)) { StdOut = NULL; } } if (StdOut == NULL) { // AttachConsole was introduced with Windows XP. (OTOH, since we // have to share the console with the shell, I'm not sure if it's // a good idea to actually attach to it.) typedef BOOL (WINAPI *ac)(DWORD); ac attach_console = kernel != NULL ? (ac)GetProcAddress(kernel, "AttachConsole") : NULL; if (attach_console != NULL && attach_console(ATTACH_PARENT_PROCESS)) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL); AttachedStdOut = true; } if (StdOut == NULL && AllocConsole()) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); } FancyStdOut = true; } } // Set the timer to be as accurate as possible if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR) TimerPeriod = 1; // Assume minimum resolution of 1 ms else TimerPeriod = tc.wPeriodMin; timeBeginPeriod (TimerPeriod); /* killough 1/98: This fixes some problems with exit handling during abnormal situations. The old code called I_Quit() to end program, while now I_Quit() is installed as an exit handler and exit() is called to exit, either normally or abnormally. */ atexit (call_terms); atterm (I_Quit); // Figure out what directory the program resides in. char *program; #ifdef _MSC_VER if (_get_pgmptr(&program) != 0) { I_FatalError("Could not determine program location."); } #else char progbuff[1024]; GetModuleFileName(0, progbuff, sizeof(progbuff)); progbuff[1023] = '\0'; program = progbuff; #endif progdir = program; program = progdir.LockBuffer(); *(strrchr(program, '\\') + 1) = '\0'; FixPathSeperator(program); progdir.Truncate((long)strlen(program)); progdir.UnlockBuffer(); HDC screenDC = GetDC(0); int dpi = GetDeviceCaps(screenDC, LOGPIXELSX); ReleaseDC(0, screenDC); width = (512 * dpi + 96 / 2) / 96; height = (384 * dpi + 96 / 2) / 96; // Many Windows structures that specify their size do so with the first // element. DEVMODE is not one of those structures. memset (&displaysettings, 0, sizeof(displaysettings)); displaysettings.dmSize = sizeof(displaysettings); EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings); x = (displaysettings.dmPelsWidth - width) / 2; y = (displaysettings.dmPelsHeight - height) / 2; if (Args->CheckParm ("-0")) { x = y = 0; } WNDCLASS WndClass; WndClass.style = 0; WndClass.lpfnWndProc = LConProc; WndClass.cbClsExtra = 0; WndClass.cbWndExtra = 0; WndClass.hInstance = hInstance; WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1)); WndClass.hCursor = LoadCursor (NULL, IDC_ARROW); WndClass.hbrBackground = NULL; WndClass.lpszMenuName = NULL; WndClass.lpszClassName = (LPCTSTR)WinClassName; /* register this new class with Windows */ if (!RegisterClass((LPWNDCLASS)&WndClass)) I_FatalError ("Could not register window class"); /* create window */ char caption[100]; mysnprintf(caption, countof(caption), "" GAMESIG " %s " X64 " (%s)", GetVersionString(), GetGitTime()); Window = CreateWindowEx( WS_EX_APPWINDOW, (LPCTSTR)WinClassName, (LPCTSTR)caption, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, x, y, width, height, (HWND) NULL, (HMENU) NULL, hInstance, NULL); if (!Window) I_FatalError ("Could not open window"); if (kernel != NULL) { typedef BOOL (WINAPI *pts)(DWORD, DWORD *); pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId"); if (pidsid != 0) { if (!pidsid (GetCurrentProcessId(), &SessionID)) { SessionID = 0; } hwtsapi32 = LoadLibraryA ("wtsapi32.dll"); if (hwtsapi32 != 0) { FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification"); if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION)) { FreeLibrary (hwtsapi32); hwtsapi32 = 0; } else { atterm (UnWTS); } } } } GetClientRect (Window, &cRect); WinWidth = cRect.right; WinHeight = cRect.bottom; CoInitialize (NULL); atterm (UnCOM); C_InitConsole (((WinWidth / 8) + 2) * 8, (WinHeight / 12) * 8, false); I_DetectOS (); D_DoomMain (); } catch (class CNoRunExit &) { I_ShutdownGraphics(); if (!batchrun) { if (FancyStdOut && !AttachedStdOut) { // Outputting to a new console window: Wait for a keypress before quitting. DWORD bytes; HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE); ShowWindow(Window, SW_HIDE); WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL); FlushConsoleInputBuffer(stdinput); SetConsoleMode(stdinput, 0); ReadConsole(stdinput, &bytes, 1, &bytes, NULL); } else if (StdOut == NULL) { ShowErrorPane(NULL); } } exit(0); } catch (class CDoomError &error) { I_ShutdownGraphics (); RestoreConView (); I_FlushBufferedConsoleStuff(); if (error.GetMessage ()) { if (!batchrun) { ShowErrorPane(error.GetMessage()); } else { Printf("%s\n", error.GetMessage()); } } exit (-1); } }
bool FZipFile::Open(bool quiet) { DWORD centraldir = Zip_FindCentralDir(Reader); FZipEndOfCentralDirectory info; int skipped = 0; Lumps = NULL; if (centraldir == 0) { if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", Filename); return false; } // Read the central directory info. Reader->Seek(centraldir, SEEK_SET); Reader->Read(&info, sizeof(FZipEndOfCentralDirectory)); // No multi-disk zips! if (info.NumEntries != info.NumEntriesOnAllDisks || info.FirstDisk != 0 || info.DiskNumber != 0) { if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", Filename); return false; } NumLumps = LittleShort(info.NumEntries); Lumps = new FZipLump[NumLumps]; // Load the entire central directory. Too bad that this contains variable length entries... int dirsize = LittleLong(info.DirectorySize); void *directory = malloc(dirsize); Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET); Reader->Read(directory, dirsize); char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; for (DWORD i = 0; i < NumLumps; i++) { FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; int len = LittleShort(zip_fh->NameLength); FString name(dirptr + sizeof(FZipCentralDirectoryInfo), len); dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + LittleShort(zip_fh->CommentLength); if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file. { free(directory); if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename); return false; } // skip Directories if (name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0) { skipped++; continue; } // Ignore unknown compression formats zip_fh->Method = LittleShort(zip_fh->Method); if (zip_fh->Method != METHOD_STORED && zip_fh->Method != METHOD_DEFLATE && zip_fh->Method != METHOD_LZMA && zip_fh->Method != METHOD_BZIP2 && zip_fh->Method != METHOD_IMPLODE && zip_fh->Method != METHOD_SHRINK) { if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", Filename, name.GetChars(), zip_fh->Method); skipped++; continue; } // Also ignore encrypted entries zip_fh->Flags = LittleShort(zip_fh->Flags); if (zip_fh->Flags & ZF_ENCRYPTED) { if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name.GetChars()); skipped++; continue; } FixPathSeperator(name); name.ToLower(); lump_p->LumpNameSetup(name); lump_p->LumpSize = LittleLong(zip_fh->UncompressedSize); lump_p->Owner = this; // The start of the Reader will be determined the first time it is accessed. lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; lump_p->Method = BYTE(zip_fh->Method); lump_p->GPFlags = zip_fh->Flags; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->CheckEmbedded(); // Ignore some very specific names if (0 == stricmp("dehacked.exe", name)) { memset(lump_p->Name, 0, sizeof(lump_p->Name)); } lump_p++; } // Resize the lump record array to its actual size NumLumps -= skipped; free(directory); if (!quiet && !batchrun) Printf(TEXTCOLOR_NORMAL ", %d lumps\n", NumLumps); PostProcessArchive(&Lumps[0], sizeof(FZipLump)); return true; }
void gl_InitModels() { int Lump, lastLump; FString path; int index, surface; int i; FSpriteModelFrame smf; lastLump = 0; for(unsigned i=0;i<Models.Size();i++) { delete Models[i]; } Models.Clear(); SpriteModelFrames.Clear(); DeleteModelHash(); // First, create models for each voxel for (unsigned i = 0; i < Voxels.Size(); i++) { FVoxelModel *md = new FVoxelModel(Voxels[i], false); Voxels[i]->VoxelIndex = Models.Push(md); } // now create GL model frames for the voxeldefs for (unsigned i = 0; i < VoxelDefs.Size(); i++) { FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex]; memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex; smf.skinIDs[0] = md->GetPaletteTexture(); smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees; if (VoxelDefs[i]->PlacedSpin != 0) { smf.yrotate = 1.f; smf.rotationSpeed = VoxelDefs[i]->PlacedSpin / 55.55f; smf.flags |= MDL_ROTATING; } VoxelDefs[i]->VoxeldefIndex = SpriteModelFrames.Push(smf); if (VoxelDefs[i]->PlacedSpin != VoxelDefs[i]->DroppedSpin) { if (VoxelDefs[i]->DroppedSpin != 0) { smf.yrotate = 1.f; smf.rotationSpeed = VoxelDefs[i]->DroppedSpin / 55.55f; smf.flags |= MDL_ROTATING; } else { smf.yrotate = 0; smf.rotationSpeed = 0; smf.flags &= ~MDL_ROTATING; } SpriteModelFrames.Push(smf); } } memset(&smf, 0, sizeof(smf)); smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) { FScanner sc(Lump); while (sc.GetString()) { if (sc.Compare("model")) { path = ""; sc.MustGetString(); memset(&smf, 0, sizeof(smf)); smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1; smf.xscale=smf.yscale=smf.zscale=1.f; smf.type = PClass::FindClass(sc.String); if (!smf.type || smf.type->Defaults == nullptr) { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("path")) { sc.MustGetString(); FixPathSeperator(sc.String); path = sc.String; if (path[(int)path.Len()-1]!='/') path+='/'; } else if (sc.Compare("model")) { sc.MustGetNumber(); index = sc.Number; if (index < 0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); smf.modelIDs[index] = FindModel(path.GetChars(), sc.String); if (smf.modelIDs[index] == -1) { Printf("%s: model not found in %s\n", sc.String, path.GetChars()); } } else if (sc.Compare("scale")) { sc.MustGetFloat(); smf.xscale = sc.Float; sc.MustGetFloat(); smf.yscale = sc.Float; sc.MustGetFloat(); smf.zscale = sc.Float; } // [BB] Added zoffset reading. // Now it must be considered deprecated. else if (sc.Compare("zoffset")) { sc.MustGetFloat(); smf.zoffset=sc.Float; } // Offset reading. else if (sc.Compare("offset")) { sc.MustGetFloat(); smf.xoffset = sc.Float; sc.MustGetFloat(); smf.yoffset = sc.Float; sc.MustGetFloat(); smf.zoffset = sc.Float; } // angleoffset, pitchoffset and rolloffset reading. else if (sc.Compare("angleoffset")) { sc.MustGetFloat(); smf.angleoffset = sc.Float; } else if (sc.Compare("pitchoffset")) { sc.MustGetFloat(); smf.pitchoffset = sc.Float; } else if (sc.Compare("rolloffset")) { sc.MustGetFloat(); smf.rolloffset = sc.Float; } // [BB] Added model flags reading. else if (sc.Compare("ignoretranslation")) { smf.flags |= MDL_IGNORETRANSLATION; } else if (sc.Compare("pitchfrommomentum")) { smf.flags |= MDL_PITCHFROMMOMENTUM; } else if (sc.Compare("inheritactorpitch")) { smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION; } else if (sc.Compare("inheritactorroll")) { smf.flags |= MDL_USEACTORROLL; } else if (sc.Compare("useactorpitch")) { smf.flags |= MDL_USEACTORPITCH; } else if (sc.Compare("useactorroll")) { smf.flags |= MDL_USEACTORROLL; } else if (sc.Compare("rotating")) { smf.flags |= MDL_ROTATING; smf.xrotate = 0.; smf.yrotate = 1.; smf.zrotate = 0.; smf.rotationCenterX = 0.; smf.rotationCenterY = 0.; smf.rotationCenterZ = 0.; smf.rotationSpeed = 1.; } else if (sc.Compare("rotation-speed")) { sc.MustGetFloat(); smf.rotationSpeed = sc.Float; } else if (sc.Compare("rotation-vector")) { sc.MustGetFloat(); smf.xrotate = sc.Float; sc.MustGetFloat(); smf.yrotate = sc.Float; sc.MustGetFloat(); smf.zrotate = sc.Float; } else if (sc.Compare("rotation-center")) { sc.MustGetFloat(); smf.rotationCenterX = sc.Float; sc.MustGetFloat(); smf.rotationCenterY = sc.Float; sc.MustGetFloat(); smf.rotationCenterZ = sc.Float; } else if (sc.Compare("interpolatedoubledframes")) { smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES; } else if (sc.Compare("nointerpolation")) { smf.flags |= MDL_NOINTERPOLATION; } else if (sc.Compare("skin")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.skinIDs[index]=FNullTextureID(); } else { smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String); if (!smf.skinIDs[index].isValid()) { Printf("Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("surfaceskin")) { sc.MustGetNumber(); index = sc.Number; sc.MustGetNumber(); surface = sc.Number; if (index<0 || index >= MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (surface<0 || surface >= MD3_MAX_SURFACES) { sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.surfaceskinIDs[index][surface] = FNullTextureID(); } else { smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String); if (!smf.surfaceskinIDs[index][surface].isValid()) { Printf("Surface Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("frameindex") || sc.Compare("frame")) { bool isframe=!!sc.Compare("frame"); sc.MustGetString(); smf.sprite = -1; for (i = 0; i < (int)sprites.Size (); ++i) { if (strnicmp (sprites[i].name, sc.String, 4) == 0) { if (sprites[i].numframes==0) { //sc.ScriptError("Sprite %s has no frames", sc.String); } smf.sprite = i; break; } } if (smf.sprite==-1) { sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars()); } sc.MustGetString(); FString framechars = sc.String; sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (isframe) { sc.MustGetString(); if (smf.modelIDs[index] != -1) { FModel *model = Models[smf.modelIDs[index]]; smf.modelframes[index] = model->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars()); } else smf.modelframes[index] = -1; } else { sc.MustGetNumber(); smf.modelframes[index] = sc.Number; } for(i=0; framechars[i]>0; i++) { char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int c = toupper(framechars[i])-'A'; if (c<0 || c>=29) { sc.ScriptError("Invalid frame character %c found", c+'A'); } if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); GetDefaultByType(smf.type)->hasmodel = true; map[c]=1; } } else { sc.ScriptMessage("Unrecognized string \"%s\"", sc.String); } } } } } // create a hash table for quick access SpriteModelHash = new int[SpriteModelFrames.Size ()]; atterm(DeleteModelHash); memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int)); for (i = 0; i < (int)SpriteModelFrames.Size (); i++) { int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size (); SpriteModelFrames[i].hashnext = SpriteModelHash[j]; SpriteModelHash[j]=i; } }
static EIWADType IdentifyVersion (TArray<FString> &wadfiles, const char *iwad, const char *zdoom_wad) { WadStuff wads[countof(IWADNames)]; size_t foundwads[NUM_IWAD_TYPES] = { 0 }; const char *iwadparm = Args->CheckValue ("-iwad"); size_t numwads; int pickwad; size_t i; bool iwadparmfound = false; FString custwad; if (iwadparm == NULL && iwad != NULL && *iwad != 0) { iwadparm = iwad; } if (iwadparm) { custwad = iwadparm; FixPathSeperator (custwad); if (CheckIWAD (custwad, wads)) { // -iwad parameter was a directory iwadparm = NULL; } else { DefaultExtension (custwad, ".wad"); iwadparm = custwad; IWADNames[0] = iwadparm; CheckIWAD ("", wads); } } if (iwadparm == NULL || wads[0].Path.IsEmpty()) { if (GameConfig->SetSection ("IWADSearch.Directories")) { const char *key; const char *value; while (GameConfig->NextInSection (key, value)) { if (stricmp (key, "Path") == 0) { FString nice = NicePath(value); FixPathSeperator(nice); CheckIWAD(nice, wads); } } } #ifdef _WIN32 FString steam_path = I_GetSteamPath(); if (steam_path.IsNotEmpty()) { static const char *const steam_dirs[] = { "doom 2/base", "final doom/base", "heretic shadow of the serpent riders/base", "hexen/base", "hexen deathkings of the dark citadel/base", "ultimate doom/base" }; steam_path += "/SteamApps/common/"; for (i = 0; i < countof(steam_dirs); ++i) { CheckIWAD (steam_path + steam_dirs[i], wads); } } #endif } if (iwadparm != NULL && !wads[0].Path.IsEmpty()) { iwadparmfound = true; } for (i = numwads = 0; i < countof(IWADNames); i++) { if (!wads[i].Path.IsEmpty()) { if (i != numwads) { wads[numwads] = wads[i]; } foundwads[wads[numwads].Type] = numwads + 1; numwads++; } } if (foundwads[IWAD_HexenDK] && !foundwads[IWAD_Hexen]) { // Cannot play Hexen DK without Hexen size_t kill = foundwads[IWAD_HexenDK]; for (i = kill; i < numwads; ++i) { wads[i - 1] = wads[i]; } numwads--; foundwads[IWAD_HexenDK] = 0; for (i = 0; i < NUM_IWAD_TYPES; ++i) { if (foundwads[i] > kill) { foundwads[i]--; } } } if (numwads == 0) // [BB] Skulltag uses Rivecoder's IWAD setup screen now (only available under Windows). #ifdef _WIN32 throw CNoIWADError(); // [RC] #else { I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n" "Did you install "GAMENAME" properly? You can do either of the following:\n" "\n" "1. Place one or more of these wads in the same directory as "GAMENAME".\n" "2. Edit your "GAMENAMELOWERCASE"-username.ini and add the directories of your iwads\n" "to the list beneath [IWADSearch.Directories]"); } #endif pickwad = 0; if (!iwadparmfound && numwads > 1) { int defiwad = 0; // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') { for (i = 0; i < numwads; ++i) { FString basename = ExtractFileBase (wads[i].Path); if (stricmp (basename, defaultiwad) == 0) { defiwad = (int)i; break; } } } pickwad = I_PickIWad (wads, (int)numwads, queryiwad, defiwad); if (pickwad >= 0) { // The newly selected IWAD becomes the new default FString basename = ExtractFileBase (wads[pickwad].Path); defaultiwad = basename; } } if (pickwad < 0) exit (0); // zdoom.pk3 must always be the first file loaded and the IWAD second. D_AddFile (wadfiles, zdoom_wad); if (wads[pickwad].Type == IWAD_HexenDK) { // load hexen.wad before loading hexdd.wad D_AddFile (wadfiles, wads[foundwads[IWAD_Hexen]-1].Path); } D_AddFile (wadfiles, wads[pickwad].Path); if (wads[pickwad].Type == IWAD_Strife) { // Try to load voices.wad along with strife1.wad long lastslash = wads[pickwad].Path.LastIndexOf ('/'); FString path; if (lastslash == -1) { path = "";// wads[pickwad].Path; } else { path = FString (wads[pickwad].Path.GetChars(), lastslash + 1); } path += "voices.wad"; D_AddFile (wadfiles, path); } return wads[pickwad].Type; }
int FIWadManager::IdentifyVersion (TArray<FString> &wadfiles, const char *iwad, const char *zdoom_wad) { TArray<WadStuff> wads; TArray<size_t> foundwads; const char *iwadparm = Args->CheckValue ("-iwad"); size_t numwads; int pickwad; size_t i; bool iwadparmfound = false; FString custwad; ParseIWadInfos(zdoom_wad); wads.Resize(mIWadNames.Size()); foundwads.Resize(mIWads.Size()); memset(&foundwads[0], 0, foundwads.Size() * sizeof(foundwads[0])); if (iwadparm == NULL && iwad != NULL && *iwad != 0) { iwadparm = iwad; } if (iwadparm) { custwad = iwadparm; FixPathSeperator (custwad); if (CheckIWAD (custwad, &wads[0])) { // -iwad parameter was a directory iwadparm = NULL; } else { DefaultExtension (custwad, ".wad"); iwadparm = custwad; mIWadNames[0] = custwad; CheckIWAD ("", &wads[0]); } } if (iwadparm == NULL || wads[0].Path.IsEmpty() || mIWads[wads[0].Type].Required.IsNotEmpty()) { if (GameConfig->SetSection ("IWADSearch.Directories")) { const char *key; const char *value; while (GameConfig->NextInSection (key, value)) { if (stricmp (key, "Path") == 0) { FString nice = NicePath(value); FixPathSeperator(nice); CheckIWAD(nice, &wads[0]); } } } #ifdef _WIN32 FString steam_path = I_GetSteamPath(); if (steam_path.IsNotEmpty()) { static const char *const steam_dirs[] = { "doom 2/base", "final doom/base", "heretic shadow of the serpent riders/base", "hexen/base", "hexen deathkings of the dark citadel/base", "ultimate doom/base", "DOOM 3 BFG Edition/base/wads" }; steam_path += "/SteamApps/common/"; for (i = 0; i < countof(steam_dirs); ++i) { CheckIWAD (steam_path + steam_dirs[i], &wads[0]); } } #endif } if (iwadparm != NULL && !wads[0].Path.IsEmpty()) { iwadparmfound = true; } for (i = numwads = 0; i < mIWadNames.Size(); i++) { if (!wads[i].Path.IsEmpty()) { if (i != numwads) { wads[numwads] = wads[i]; } foundwads[wads[numwads].Type] = numwads + 1; numwads++; } } for (unsigned i=0; i<mIWads.Size(); i++) { if (mIWads[i].Required.IsNotEmpty() && foundwads[i]) { bool found = false; // needs to be loaded with another IWAD (HexenDK) for (unsigned j=0; j<mIWads.Size(); j++) { if (!mIWads[i].Required.Compare(mIWads[j].Name)) { if (foundwads[j]) { found = true; mIWads[i].preload = j; } break; } } // The required WAD is not there so this one can't be used and must be deleted from the list if (!found) { size_t kill = foundwads[i]; for (size_t j = kill; j < numwads; ++j) { wads[j - 1] = wads[j]; } numwads--; foundwads[i] = 0; for (unsigned j = 0; j < foundwads.Size(); ++j) { if (foundwads[j] > kill) { foundwads[j]--; } } } } } if (numwads == 0) { I_FatalError ("Cannot find a game IWAD (doom.wad, doom2.wad, heretic.wad, etc.).\n" "Did you install ZDoom properly? You can do either of the following:\n" "\n" "1. Place one or more of these wads in the same directory as ZDoom.\n" "2. Edit your zdoom-username.ini and add the directories of your iwads\n" "to the list beneath [IWADSearch.Directories]"); } pickwad = 0; if ((!iwadparmfound && numwads > 1) || I_ForcePickIWAD()) { int defiwad = 0; // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') { for (i = 0; i < numwads; ++i) { FString basename = ExtractFileBase (wads[i].Path); if (stricmp (basename, defaultiwad) == 0) { defiwad = (int)i; break; } } } pickwad = I_PickIWad (&wads[0], (int)numwads, queryiwad, defiwad); if (pickwad >= 0) { // The newly selected IWAD becomes the new default FString basename = ExtractFileBase (wads[pickwad].Path); defaultiwad = basename; } } if (pickwad < 0) exit (0); // zdoom.pk3 must always be the first file loaded and the IWAD second. wadfiles.Clear(); D_AddFile (wadfiles, zdoom_wad); if (mIWads[wads[pickwad].Type].preload >= 0) { D_AddFile (wadfiles, wads[foundwads[mIWads[wads[pickwad].Type].preload]-1].Path); } D_AddFile (wadfiles, wads[pickwad].Path); for (unsigned i=0; i < mIWads[wads[pickwad].Type].Load.Size(); i++) { long lastslash = wads[pickwad].Path.LastIndexOf ('/'); FString path; if (lastslash == -1) { path = "";// wads[pickwad].Path; } else { path = FString (wads[pickwad].Path.GetChars(), lastslash + 1); } path += mIWads[wads[pickwad].Type].Load[i]; D_AddFile (wadfiles, path); } return wads[pickwad].Type; }
void DoMain (HINSTANCE hInstance) { LONG WinWidth, WinHeight; int height, width; RECT cRect; TIMECAPS tc; try { #ifdef _MSC_VER _set_new_handler (NewFailure); #endif Args.SetArgs (__argc, __argv); // Under XP, get our session ID so we can know when the user changes/locks sessions. // Since we need to remain binary compatible with older versions of Windows, we // need to extract the ProcessIdToSessionId function from kernel32.dll manually. HMODULE kernel = GetModuleHandle ("kernel32.dll"); // NASM does not support creating writeable code sections (even though this // is a perfectly valid configuration for Microsoft's COFF format), so I // need to make the self-modifying code writeable after it's already loaded. #ifdef USEASM { BYTE *module = (BYTE *)GetModuleHandle (NULL); IMAGE_DOS_HEADER *dosHeader = (IMAGE_DOS_HEADER *)module; IMAGE_NT_HEADERS *ntHeaders = (IMAGE_NT_HEADERS *)(module + dosHeader->e_lfanew); IMAGE_SECTION_HEADER *sections = IMAGE_FIRST_SECTION (ntHeaders); int i; LPVOID *start = NULL; SIZE_T size = 0; DWORD oldprotect; for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i) { if (memcmp (sections[i].Name, ".rtext\0", 8) == 0) { start = (LPVOID *)(sections[i].VirtualAddress + module); size = sections[i].Misc.VirtualSize; break; } } // I think these pages need to be mapped PAGE_EXECUTE_WRITECOPY (based on the // description of PAGE_WRITECOPY), but PAGE_EXECUTE_READWRITE seems to work // just as well; two instances of the program can be running with different // resolutions at the same time either way. Perhaps the file mappings for // executables are created with PAGE_WRITECOPY, so any attempts to give them // write access are automatically transformed to copy-on-write? // // This used to be PAGE_EXECUTE_WRITECOPY until Timmie found out Win9x doesn't // support it, although the MSDN does not indicate it. if (!VirtualProtect (start, size, PAGE_EXECUTE_READWRITE, &oldprotect)) { I_FatalError ("The self-modifying code section code not be made writeable."); } } #endif // Set the timer to be as accurate as possible if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR) TimerPeriod = 1; // Assume minimum resolution of 1 ms else TimerPeriod = tc.wPeriodMin; timeBeginPeriod (TimerPeriod); /* killough 1/98: This fixes some problems with exit handling during abnormal situations. The old code called I_Quit() to end program, while now I_Quit() is installed as an exit handler and exit() is called to exit, either normally or abnormally. */ atexit (call_terms); atterm (I_Quit); // Figure out what directory the program resides in. GetModuleFileName (NULL, progdir, 1024); *(strrchr (progdir, '\\') + 1) = 0; FixPathSeperator (progdir); // [BC] When hosting, spawn a console dialog box instead of creating a window. if ( Args.CheckParm( "-host" )) { // This never returns. DialogBox( g_hInst, MAKEINTRESOURCE( IDD_SERVERDIALOG ), NULL/*(HWND)Window*/, SERVERCONSOLE_ServerDialogBoxCallback ); } else { height = GetSystemMetrics (SM_CYFIXEDFRAME) * 2 + GetSystemMetrics (SM_CYCAPTION) + 12 * 32; width = GetSystemMetrics (SM_CXFIXEDFRAME) * 2 + 8 * 78; TheInvisibleCursor = LoadCursor (hInstance, MAKEINTRESOURCE(IDC_INVISIBLECURSOR)); TheArrowCursor = LoadCursor (NULL, IDC_ARROW); WndClass.style = 0; WndClass.lpfnWndProc = WndProc; WndClass.cbClsExtra = 0; WndClass.cbWndExtra = 0; WndClass.hInstance = hInstance; WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON5)); WndClass.hCursor = TheArrowCursor; WndClass.hbrBackground = NULL; WndClass.lpszMenuName = NULL; WndClass.lpszClassName = (LPCTSTR)WinClassName; /* register this new class with Windows */ if (!RegisterClass((LPWNDCLASS)&WndClass)) I_FatalError ("Could not register window class"); /* create window */ Window = CreateWindow((LPCTSTR)WinClassName, (LPCTSTR) GAMESIG " v" DOTVERSIONSTR " (" __DATE__ ")", WS_OVERLAPPEDWINDOW, 0/*CW_USEDEFAULT*/, 1/*CW_USEDEFAULT*/, width, height, (HWND) NULL, (HMENU) NULL, hInstance, NULL); if (!Window) I_FatalError ("Could not open window"); WndClass.lpfnWndProc = LConProc; WndClass.lpszClassName = (LPCTSTR)ConClassName; if (RegisterClass ((LPWNDCLASS)&WndClass)) { ConWindow = CreateWindowEx ( WS_EX_PALETTEWINDOW & (~WS_EX_TOPMOST), (LPCTSTR)ConClassName, (LPCTSTR) "Skulltag Startup Viewer", WS_OVERLAPPEDWINDOW/* | WS_VISIBLE*/, CW_USEDEFAULT, CW_USEDEFAULT, 512, 384, Window, NULL, hInstance, NULL); } if (kernel != 0) { typedef BOOL (WINAPI *pts)(DWORD, DWORD *); pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId"); if (pidsid != 0) { if (!pidsid (GetCurrentProcessId(), &SessionID)) { SessionID = 0; } hwtsapi32 = LoadLibraryA ("wtsapi32.dll"); if (hwtsapi32 != 0) { FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification"); if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION)) { FreeLibrary (hwtsapi32); hwtsapi32 = 0; } else { atterm (UnWTS); } } } } GetClientRect (Window, &cRect); WinWidth = cRect.right; WinHeight = cRect.bottom; } CoInitialize (NULL); atterm (UnCOM); C_InitConsole (((WinWidth / 8) + 2) * 8, (WinHeight / 12) * 8, false); I_DetectOS (); D_DoomMain (); } catch (class CDoomError &error) { I_ShutdownHardware (); SetWindowPos (Window, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW); if (ConWindow != NULL) { ShowWindow (ConWindow, SW_SHOW); } if (error.GetMessage ()) MessageBox (Window, error.GetMessage(), "Skulltag Fatal Error", MB_OK|MB_ICONSTOP|MB_TASKMODAL); exit (-1); } }
void gl_InitModels() { int Lump, lastLump; FString path; int index; int i; FSpriteModelFrame smf; lastLump = 0; memset(&smf, 0, sizeof(smf)); while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) { FScanner sc(Lump); while (sc.GetString()) { if (sc.Compare("model")) { sc.MustGetString(); memset(&smf, 0, sizeof(smf)); smf.xscale=smf.yscale=smf.zscale=1.f; smf.type = PClass::FindClass(sc.String); if (!smf.type || smf.type->Defaults == NULL) { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } GetDefaultByType(smf.type)->hasmodel=true; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("path")) { sc.MustGetString(); FixPathSeperator(sc.String); path = sc.String; if (path[(int)path.Len()-1]!='/') path+='/'; } else if (sc.Compare("model")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); smf.models[index] = FindModel(path.GetChars(), sc.String); if (!smf.models[index]) { Printf("%s: model not found\n", sc.String); } } else if (sc.Compare("scale")) { sc.MustGetFloat(); smf.xscale=sc.Float; sc.MustGetFloat(); smf.yscale=sc.Float; sc.MustGetFloat(); smf.zscale=sc.Float; } // [BB] Added zoffset reading. else if (sc.Compare("zoffset")) { sc.MustGetFloat(); smf.zoffset=sc.Float; } // [BB] Added model flags reading. else if (sc.Compare("ignoretranslation")) { smf.flags |= MDL_IGNORETRANSLATION; } else if (sc.Compare("pitchfrommomentum")) { smf.flags |= MDL_PITCHFROMMOMENTUM; } else if (sc.Compare("rotating")) { smf.flags |= MDL_ROTATING; smf.xrotate = 0.; smf.yrotate = 1.; smf.zrotate = 0.; smf.rotationCenterX = 0.; smf.rotationCenterY = 0.; smf.rotationCenterZ = 0.; smf.rotationSpeed = 1.; } else if (sc.Compare("rotation-speed")) { sc.MustGetFloat(); smf.rotationSpeed = sc.Float; } else if (sc.Compare("rotation-vector")) { sc.MustGetFloat(); smf.xrotate = sc.Float; sc.MustGetFloat(); smf.yrotate = sc.Float; sc.MustGetFloat(); smf.zrotate = sc.Float; } else if (sc.Compare("rotation-center")) { sc.MustGetFloat(); smf.rotationCenterX = sc.Float; sc.MustGetFloat(); smf.rotationCenterY = sc.Float; sc.MustGetFloat(); smf.rotationCenterZ = sc.Float; } else if (sc.Compare("interpolatedoubledframes")) { smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES; } else if (sc.Compare("nointerpolation")) { smf.flags |= MDL_NOINTERPOLATION; } else if (sc.Compare("alignangle")) { smf.flags |= MDL_ALIGNANGLE; } else if (sc.Compare("alignpitch")) { smf.flags |= MDL_ALIGNPITCH; } else if (sc.Compare("rollagainstangle")) { smf.flags |= MDL_ROLLAGAINSTANGLE; } else if (sc.Compare("skin")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.skins[index]=NULL; } else { smf.skins[index]=LoadSkin(path.GetChars(), sc.String); if (smf.skins[index] == NULL) { Printf("Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("frameindex") || sc.Compare("frame")) { bool isframe=!!sc.Compare("frame"); sc.MustGetString(); smf.sprite = -1; for (i = 0; i < (int)sprites.Size (); ++i) { if (strncmp (sprites[i].name, sc.String, 4) == 0) { if (sprites[i].numframes==0) { //sc.ScriptError("Sprite %s has no frames", sc.String); } smf.sprite = i; break; } } if (smf.sprite==-1) { sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars()); } sc.MustGetString(); FString framechars = sc.String; sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (isframe) { sc.MustGetString(); if (smf.models[index]!=NULL) { smf.modelframes[index] = smf.models[index]->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars()); } else smf.modelframes[index] = -1; } else { sc.MustGetNumber(); smf.modelframes[index] = sc.Number; } for(i=0; framechars[i]>0; i++) { char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int c = toupper(framechars[i])-'A'; if (c<0 || c>=29) { sc.ScriptError("Invalid frame character %c found", c+'A'); } if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); map[c]=1; } } } } } } // create a hash table for quick access SpriteModelHash = new int[SpriteModelFrames.Size ()]; atterm(DeleteModelHash); memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int)); for (i = 0; i < (int)SpriteModelFrames.Size (); i++) { int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size (); SpriteModelFrames[i].hashnext = SpriteModelHash[j]; SpriteModelHash[j]=i; } }
bool FZipFile::Open(bool quiet) { DWORD centraldir = Zip_FindCentralDir(Reader); FZipEndOfCentralDirectory info; int skipped = 0; Lumps = NULL; if (centraldir == 0) { if (!quiet) Printf("\n%s: ZIP file corrupt!\n", Filename); return false; } // Read the central directory info. Reader->Seek(centraldir, SEEK_SET); Reader->Read(&info, sizeof(FZipEndOfCentralDirectory)); // No multi-disk zips! if (info.NumEntries != info.NumEntriesOnAllDisks || info.FirstDisk != 0 || info.DiskNumber != 0) { if (!quiet) Printf("\n%s: Multipart Zip files are not supported.\n", Filename); return false; } NumLumps = LittleShort(info.NumEntries); Lumps = new FZipLump[NumLumps]; // Load the entire central directory. Too bad that this contains variable length entries... void *directory = malloc(LittleLong(info.DirectorySize)); Reader->Seek(LittleLong(info.DirectoryOffset), SEEK_SET); Reader->Read(directory, LittleLong(info.DirectorySize)); char *dirptr = (char*)directory; FZipLump *lump_p = Lumps; for (DWORD i = 0; i < NumLumps; i++) { FZipCentralDirectoryInfo *zip_fh = (FZipCentralDirectoryInfo *)dirptr; char name[256]; int len = LittleShort(zip_fh->NameLength); strncpy(name, dirptr + sizeof(FZipCentralDirectoryInfo), MIN<int>(len, 255)); name[len] = 0; dirptr += sizeof(FZipCentralDirectoryInfo) + LittleShort(zip_fh->NameLength) + LittleShort(zip_fh->ExtraLength) + LittleShort(zip_fh->CommentLength); // skip Directories if (name[len - 1] == '/' && LittleLong(zip_fh->UncompressedSize) == 0) { skipped++; continue; } // Ignore unknown compression formats zip_fh->Method = LittleShort(zip_fh->Method); if (zip_fh->Method != METHOD_STORED && zip_fh->Method != METHOD_DEFLATE && zip_fh->Method != METHOD_LZMA && zip_fh->Method != METHOD_BZIP2 && zip_fh->Method != METHOD_IMPLODE && zip_fh->Method != METHOD_SHRINK) { if (!quiet) Printf("\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", Filename, name, zip_fh->Method); skipped++; continue; } // Also ignore encrypted entries zip_fh->Flags = LittleShort(zip_fh->Flags); if (zip_fh->Flags & ZF_ENCRYPTED) { if (!quiet) Printf("\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name); skipped++; continue; } FixPathSeperator(name); strlwr(name); lump_p->LumpNameSetup(name); lump_p->LumpSize = LittleLong(zip_fh->UncompressedSize); lump_p->Owner = this; // The start of the Reader will be determined the first time it is accessed. lump_p->Flags = LUMPF_ZIPFILE | LUMPFZIP_NEEDFILESTART; lump_p->Method = BYTE(zip_fh->Method); lump_p->GPFlags = zip_fh->Flags; lump_p->CompressedSize = LittleLong(zip_fh->CompressedSize); lump_p->Position = LittleLong(zip_fh->LocalHeaderOffset); lump_p->CheckEmbedded(); lump_p++; } // Resize the lump record array to its actual size NumLumps -= skipped; free(directory); if (!quiet) Printf(", %d lumps\n", NumLumps); // Entries in Zips are sorted alphabetically. qsort(Lumps, NumLumps, sizeof(FZipLump), lumpcmp); return true; }
/* This adds a directory to the path list */ void PathExpander::addToPathlist(const char *s) { FString copy = s; FixPathSeperator(copy); PathList.Push(copy); }