Commits

Palmer, 2E0EOL committed 82a4b8f

Unpack SprEd archive, but delete *.obj

  • Participants
  • Parent commits a71fd8b

Comments (0)

Files changed (23)

+#ifndef __INC_MAINWND_H
+#define __INC_MAINWND_H
+/*-------------------------------------------------------------------------*/
+/* Include this header for main window control */
+
+#ifndef __cplusplus /* C compiler? */
+#	error ("Oops, C unit's can't control the framework or derivatives")
+#endif /*!__cplusplus*/
+//---------------------------------------------------------------------------
+class TMainWindow : public TDialog
+{
+public:
+	TMainWindow(TWindow* parent = 0);
+   ~TMainWindow();
+   void SetupWindow();
+
+protected:
+	// Event handlers
+	void CmFileOpen(); // Hanlder for File|Open menu option
+	void CmFileExit(); // Handler for File|Exit menu option
+   void CmHelpAbout(); // Handler for Help|About menu option
+	void ResObjExtChkClick(); // Clicked on "Extended header checkbox"
+   void GrpMemChkClick(); // Clicked on "Member of group checkbox"
+
+   // Others
+   void DoOpen(const char* FileName); /* Opens a file using a filename */
+   void SprFile2Win(FILE* SprFile); // Loads info onto a mainform
+
+private:
+		// Controls
+		TGroupBox *ResObjGrp, *SpriteGrp;
+      TEdit *GlblResIDEdit, *ResDescEdit, *AuthorEdit, *CommentsEdit, *SprIDEdit, *SprGrpIDEdit, *SumEdit;
+      TCheckBox *ResObjExtChk, *GrpMemChk;
+      TComboBox *StdGrpPos;
+
+      S_TEMPFILE _tempFile; // Temporary file management
+
+	DECLARE_RESPONSE_TABLE(TMainWindow);
+};
+//---------------------------------------------------------------------------
+DEFINE_RESPONSE_TABLE1(TMainWindow, TWindow)
+	EV_COMMAND(CM_FILEOPEN, CmFileOpen),
+	EV_COMMAND(CM_FILEEXIT, CmFileExit),
+   EV_COMMAND(CM_HELPABOUT, CmHelpAbout),
+   EV_BN_CLICKED(IDC_RESOBJ_EXTCHK, ResObjExtChkClick),
+   EV_BN_CLICKED(IDC_SPR_GRPMEMCHK, GrpMemChkClick),
+END_RESPONSE_TABLE;
+/*-------------------------------------------------------------------------*/
+#endif /*__INC_MAINWND_H*/
+/* This inclusion is to load & save files under GDT's SprED */
+
+#ifndef __INC_OPENSAVE_H
+#define __INC_OPENSAVE_H
+#include "Headers\BeginCH.H"
+/*-------------------------------------------------------------------------*/
+const int opensave_OpenFile(FILE* File2Open, FILE* TemporaryFile);
+const int opensave_SaveFile(FILE* File2Save, FILE* TemporaryFile);
+
+/* Normally these functions return -1, if a positive number is
+returned, it is an index which may be passed to opensave_GetLastError().
+NOTE: I am saying 0 is a positive integer, some poeple choose to argue.
+*/
+const char* opensave_GetLastError(const int Index); /* Returns an error
+message for that error number, positives only please.  NULL is returned
+incase of failure like -1 or a large number. */
+
+/* These error numbers have been defined, do not not re-order their
+numbers because they match an array of strings.  Oh and always make
+sure the MAX indicator on the end is correct after additions or
+removals. */
+#define OPENSAVE_ERROR_NOERROR (-1)
+#define OPENSAVE_ERROR_OBJBADSIG (0) /* Resource object has bad sig */
+#define OPENSAVE_ERROR_OBJOLDVER (1) /* Res object is too old */
+#define OPENSAVE_ERROR_OBJNEWVER (2) /* Res object is too new */
+#define OPENSAVE_ERROR_STREAM (3) /* General I/O error */
+#define OPENSAVE_ERROR_EOF (4) /* EOF reading source */
+#define OPENSAVE_ERROR_MAXERROR (OPENSAVE_ERROR_EOF)
+/*-------------------------------------------------------------------------*/
+#include "Headers\EndCH.H"
+#endif /*__INC_OPENSAVE_H*/

SprEd/SprEd.DSW

Binary file added.
+#define IDD_MAINWIN (2)
+#define IDD_ABOUTBOX	(1)
+#define IDC_AB_ST	(-1)
+#define IDC_AB_STPIC	(-1)
+#define IDG_RESOBJGRP (101)
+#define IDG_SPRITEGRP (102)
+#define IDC_RESOBJ_GLBLRESID (103)
+#define IDC_RESOBJ_EXTCHK (104)
+#define IDC_RESOBJ_RESDESC	(105)
+#define IDC_RESOBJ_AUTHOR (106)
+#define IDC_RESOBJ_COMMENTS (107)
+#define IDC_STATICTEXT1	(-1)
+#define IDC_STATICTEXT2	(-1)
+#define IDC_STATICTEXT3	(-1)
+#define IDC_STATICTEXT4	(-1)
+#define IDC_STATICTEXT5	(-1)
+#define IDC_STATICTEXT6	(-1)
+#define IDC_STATICTEXT7	(-1)
+#define IDC_STATICFRAME1 (-1)
+#define IDC_SPR_ID	(108)
+#define IDC_SPR_GRPMEMCHK	(109)
+#define IDC_SPR_GROUPID	(110)
+#define IDC_SPR_STDGRPPOS	(111)
+#define IDC_SPR_SUM	(112)
+#define IDI_MAINICON	(1)
+#define IDM_MAINMENU	(1)
+#define VERSIONINFO_1	(1)
+#define CM_FILEOPEN	(11843)
+#define CM_FILECOMPILE	(11844)
+#define CM_FILEEXIT	(11845)
+#define CM_HELPTOPICS (11846)
+#define CM_HELPABOUT (11847)

SprEd/SprEd.ide

Binary file added.

SprEd/SprEd.mbt

Binary file added.

SprEd/SprEd.mrt

Binary file added.
+#ifndef __INC_SPREDTEC_H
+#define __INC_SPREDTEC_H
+/*-------------------------------------------------------------------------*/
+/* Header to access portable part of SprEdTec,
+these functions allow technical editing of compiled sprites */
+
+#ifdef __cplusplus /* C++ compiler? */
+extern "C" {
+#endif /*__cplusplus*/
+
+/* The parameter PResObjHeadEx may be ommitted if the header is not marked as
+an extended header, pass NULL to indicate this exclusion */
+
+BOOL spredtec_Write(FILE* file, const PS_RESOBJHEADER PResObjHead, const PS_RESOBJHEADEREX PResObjHeadEx, const PS_RESSPRITEHEADER PSpriteHead);
+BOOL spredtec_Read(FILE* file, PS_RESOBJHEADER PResObjHead, PS_RESOBJHEADEREX PResObjHeadEx, PS_RESSPRITEHEADER PSpriteHead);
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+/*-------------------------------------------------------------------------*/
+#endif /*__INC_SPREDTEC_H*/
+File I/O error
+File I/O error
+#ifndef __INC_TEMPFILE_H
+#define __INC_TEMPFILE_H
+#include "Headers\BeginCH.H"
+/*-------------------------------------------------------------------------*/
+typedef struct _S_TEMPFILE /* Object definition */
+{
+  /* PRIVATE */
+    FILE* _hTempFile; /* Handle of temp file, NULL if closed */
+    S_DLSTRLIB_DPSTR _tempFileName; /* Temporary file's name */
+
+  /* PUBLIC */
+  BOOL (*Open)(void*); /* Opens temp file, FALSE is returned on failure.  If Open() is called when a file is open already, the old one will be closed.  */
+  void (*Close)(void*); /* Closes temp file */
+  FILE* (*GetStreamPtr)(const void*); /* Gives the stream pointer (like a handle) for accessing the file with stdio functions.  NULL is returned if no file is open */
+} S_TEMPFILE, *PS_TEMPFILE;
+
+void S_TEMPFILE_Construct(PS_TEMPFILE); /* Object constructor, call on object before using it */
+void S_TEMPFILE_Destruct(PS_TEMPFILE); /* Object destructor, call on object before destroying it or going out of scope */
+
+/* NOTES:  Opening and closing the temp file managed by the object is like
+allocating and deallocating memory because when the file is opened it is
+created and when it is closed the file is automatically deleted. */
+/*-------------------------------------------------------------------------*/
+#include "Headers\EndCH.H"
+#endif /*__INC_TEMPFILE_H*/
+/* This ANSI C module is designed to handle the managment of a temporary
+file during the execution of SprED.  From the way a .SPR file is build
+it is clear that editing of a file in-place is difficult, since not all
+headers exist depending on flags in previous headers etc.  It is easier
+therefore, to copy the file out into an expanded format, this expanded
+format contains all headers, whether they are used or not.  Then, when
+written back, the .SPR simply is not copied the headers which aren't used.
+
+An object has support for ONE temporary file.  At time of writing I do
+not see a need for multi-file support, but this is easily accomplished.
+Create an array of this object dynamically and one has flexible dynamic
+multi-file temp support as needed.
+
+Names are generated for temp files by another module
+
+
+ - David Duncan Ross Palmer */
+
+#include <Assert.H>
+#include <StdIO.H> /* For closing and deleting the temp file after use */
+#include "Stds\DLStdInc.H" /* Daybo Logic standard inclusions header */
+#include "DLStrLib\DLStrLib.H" /* Daybo Logic's String Library */
+#pragma hdrstop
+
+#include "Replace\Replace.H" /* All replacable code */
+#include "Headers\AnsiSFnc.H"
+#include "TempFile.H" /* Our header */
+
+/* Private (static) declarations */
+static void S_TEMPFILE_DataInit(PS_TEMPFILE); /* Initializes data (normally called in constructor) */
+static void S_TEMPFILE_FuncLink(PS_TEMPFILE); /* Links C functions to pointers to functions in structure */
+
+/* Now there are private (static) but the caller has access to them, through
+the pointers to them in the structure.  Therefore to prevent them using a
+function which is a member (virtually anyway) independantly of the object,
+I have made them static so the object is used as I want it to be. */
+BOOL S_TEMPFILE_Open(void*);
+void S_TEMPFILE_Close(void*);
+FILE* S_TEMPFILE_GetStreamPtr(const void*);
+
+/*-------------------------------------------------------------------------*/
+void S_TEMPFILE_Construct(PS_TEMPFILE PObject)
+{
+  assert(PObject);
+
+  S_TEMPFILE_FuncLink(PObject); /* Link member functions to object */
+  S_TEMPFILE_DataInit(PObject); /* Initialize data members to defaults */
+
+  /* Object-member construction */
+  S_DLSTRLIB_DPSTR_Construct(&PObject->_tempFileName); /* Construct temp filename */
+}
+/*-------------------------------------------------------------------------*/
+void S_TEMPFILE_Destruct(PS_TEMPFILE PObject)
+{
+  assert(PObject);
+
+  if (PObject->_hTempFile) /* There's a temp file open not closed before destruction? (gathered by checking file stream pointer) */
+    PObject->Close(PObject); /* Make sure it's closed */
+
+  /* Object-member destruction */
+  S_DLSTRLIB_DPSTR_Destruct(&PObject->_tempFileName); /* Destroy temp filename */
+}
+/*-------------------------------------------------------------------------*/
+static void S_TEMPFILE_DataInit(PS_TEMPFILE PObject)
+{
+  assert(PObject);
+
+  PObject->_hTempFile = NULL; /* Indicates that no file is open */
+}
+/*-------------------------------------------------------------------------*/
+static void S_TEMPFILE_FuncLink(PS_TEMPFILE PObject)
+{
+  assert(PObject);
+
+  PObject->Open = S_TEMPFILE_Open;
+  PObject->Close = S_TEMPFILE_Close;
+  PObject->GetStreamPtr = S_TEMPFILE_GetStreamPtr;
+}
+/*-------------------------------------------------------------------------*/
+BOOL S_TEMPFILE_Open(void* PObject)
+{
+  /* locals */
+  PS_TEMPFILE s = (S_TEMPFILE*)PObject; /* Cast object pointer */
+  char pathname[PATHNAME_MAX+1]; /* Buffer for pathnames */
+
+  assert(s);
+  if (s->_hTempFile) /* A file is already open? */
+    s->Close(s); /* Close it before opening a new one */
+
+  replaceables_GetTempPath(sizeof(pathname)-1, pathname); /* Get the Windows temporary files path */
+  s->_hTempFile = subst_creattemp(pathname, ".TMP"); /* Create a new name for the temp file and create it and store it's stream pointer */
+  s->_tempFileName.Set(&s->_tempFileName, pathname); /* Remember the temp file's name */
+
+  /* Time to go */
+  if (s->_hTempFile) return TRUE; /* Report success if we obtained handle */
+  return FALSE; /* We failed No.1 ... do not fail me again! */
+}
+/*-------------------------------------------------------------------------*/
+void S_TEMPFILE_Close(void* PObject)
+{
+  PS_TEMPFILE s = (S_TEMPFILE*)PObject; /* Cast object pointer */
+
+  assert(s);
+  if (s->_hTempFile) /* File must be open for us to close it */
+  {
+    fclose(s->_hTempFile); /* Close temporary file */
+    s->_hTempFile = NULL; /* Remember we closed it */
+    remove(s->_tempFileName.c_str(&s->_tempFileName)); /* Delete the temporary file */
+    s->_tempFileName.Clear(&s->_tempFileName); /* Erase our memory of the filename */
+  }
+}
+/*-------------------------------------------------------------------------*/
+FILE* S_TEMPFILE_GetStreamPtr(const void* PObject)
+{
+  PS_TEMPFILE s = (S_TEMPFILE*)PObject; /* Cast object pointer */
+
+  assert(s);
+  return s->_hTempFile; /* Give stream pointer to caller */
+}
+/*-------------------------------------------------------------------------*/

SprEd/mainwnd.cpp

+/* Main window control class */
+
+#include <Owl\OwlAll.H>
+#include <String.H>
+#include <StdIO.H>
+#include "Stds\DLStdInc.H" /* Daybo Logic standard inclusions header */
+#include "DLStrLib\DLStrLib.H" /* Daybo Logic's String Library */
+#include "DLUtils\DLUtils.H" /* Daybo Logic utilities */
+#pragma hdrstop
+
+#include "TempFile.H" // Declaration of object manages temporary file
+#include "SprEd.RHI" // Resource defines
+#include "OwlStuff\SCDlg.H" // TSelfCenteringDialog
+#include "AboutBox.H" // TAboutBox
+#include "MainWnd.H" // Main window
+#include "CoppsRes.H" // Definitions for resource formats in game (TheCopps)
+#include "SprEdTec.H" // Portable core functiionallity inclusing getting header info from the temp file
+#include "OpenSave.H" // Open and save to from using temp file
+//---------------------------------------------------------------------------
+TMainWindow::TMainWindow(TWindow* parent)
+:  TDialog(parent, IDD_MAINWIN)
+{
+  /* Construct components */
+  ResObjGrp = new TGroupBox(this, IDG_RESOBJGRP);
+  SpriteGrp = new TGroupBox(this, IDG_SPRITEGRP);
+  GlblResIDEdit = new TEdit(this, IDC_RESOBJ_GLBLRESID, 31);
+  ResDescEdit = new TEdit(this, IDC_RESOBJ_RESDESC, 511);
+  AuthorEdit = new TEdit(this, IDC_RESOBJ_AUTHOR, 127);
+  CommentsEdit = new TEdit(this, IDC_RESOBJ_COMMENTS, 511);
+  SprIDEdit = new TEdit(this, IDC_SPR_ID, 31);
+  SprGrpIDEdit = new TEdit(this, IDC_SPR_GROUPID, 31);
+  SumEdit = new TEdit(this, IDC_SPR_SUM);
+  ResObjExtChk = new TCheckBox(this, IDC_RESOBJ_EXTCHK, ResObjGrp);
+  GrpMemChk = new TCheckBox(this, IDC_SPR_GRPMEMCHK, SpriteGrp);
+  StdGrpPos = new TComboBox(this, IDC_SPR_STDGRPPOS);
+
+  S_TEMPFILE_Construct(&_tempFile); // Create temp file management object
+}
+//---------------------------------------------------------------------------
+TMainWindow::~TMainWindow()
+{
+  S_TEMPFILE_Destruct(&_tempFile); // Destroy temp file manager
+}
+//---------------------------------------------------------------------------
+void TMainWindow::SetupWindow()
+{
+  TDialog::SetupWindow(); /* Call parent's version */
+}
+//---------------------------------------------------------------------------
+void TMainWindow::CmFileOpen() // User wants to open a file
+{
+  const char Filter[] = "*.spr"; // Initial filter
+  const char CustomFilter[] = "Sprites (*.spr)|*.SPR|Full monty (*.*)|*.*"; // All filters
+  const char DefExt[] = "SPR"; // Default file extension
+  TFileOpenDialog::TData shitData; // Something the dialog wants
+  shitData.Filter = new char[sizeof(Filter)]; // Allocate space to copy initial filter
+  shitData.DefExt = new char[sizeof(DefExt)]; // Allocate space to copy default extension
+  strcpy(shitData.Filter, Filter); // Copy initial filter text
+  shitData.SetFilter(CustomFilter); // Set the custom filter
+  strcpy(shitData.DefExt, DefExt); // Copy default extension
+
+  TFileOpenDialog foDlg(this, shitData, 0, "Open compiled sprite");
+
+  foDlg.Execute(); // Display open dialog now
+
+  if (shitData.FileName[0] != '\0') /* A filename specified? */
+  {
+    DoOpen(shitData.FileName); // Opens the filename using GUI function (in this class)
+  }
+
+  // Cleanup
+  if (shitData.Filter)
+  {
+    delete[] shitData.Filter;
+    shitData.Filter = NULL;
+  }
+  if (shitData.DefExt)
+  {
+    delete[] shitData.DefExt;
+    shitData.DefExt = NULL;
+  }
+}
+//---------------------------------------------------------------------------
+void TMainWindow::CmFileExit()
+{
+  CloseWindow(); // Request to close main window, and therefore the app
+}
+//---------------------------------------------------------------------------
+void TMainWindow::CmHelpAbout()
+{
+  TAboutBox AboutBox(this); // About box constructed locally
+
+  AboutBox.Execute(); // Modally display it
+}
+//---------------------------------------------------------------------------
+void TMainWindow::ResObjExtChkClick()
+{
+  /* locals */
+  uint Check; /* Check state switcher */
+  NATIVEBOOLTYPE WindowEnablement; /* Determines window enablement and puts it here later */
+
+  Check = ResObjExtChk->GetCheck(); // Save check
+  Check = !Check; // Negate check logically
+  ResObjExtChk->SetCheck(Check); // Set new check state
+
+  /* NOTE: Logical negation of the checkbox means that if is in the
+  third state (BF_GRAYED) it will be set to BF_UNCHECKED and that
+  will go to BF_CHECKED, then back to BF_UNCHECKED.  So this means
+  I can set the checkbox to grayed but the user cannot */
+
+  (Check == BF_UNCHECKED) ? WindowEnablement = _FALSE : WindowEnablement = _TRUE;
+  ResDescEdit->EnableWindow(WindowEnablement);
+  AuthorEdit->EnableWindow(WindowEnablement);
+  CommentsEdit->EnableWindow(WindowEnablement);
+}
+//---------------------------------------------------------------------------
+void TMainWindow::GrpMemChkClick()
+{
+  /* locals */
+  uint Check; /* Check state switcher */
+  NATIVEBOOLTYPE WindowEnablement; /* Determines window enablement and puts it here later */
+
+  Check = GrpMemChk->GetCheck(); // Save check
+  Check = !Check; // Negate check logically
+  GrpMemChk->SetCheck(Check); // Set new check state
+
+  /* NOTE: Logical negation of the checkbox means that if is in the
+  third state (BF_GRAYED) it will be set to BF_UNCHECKED and that
+  will go to BF_CHECKED, then back to BF_UNCHECKED.  So this means
+  I can set the checkbox to grayed but the user cannot */
+
+  (Check == BF_UNCHECKED) ? WindowEnablement = _FALSE : WindowEnablement = _TRUE;
+  SprGrpIDEdit->EnableWindow(WindowEnablement);
+  StdGrpPos->EnableWindow(WindowEnablement);
+}
+//---------------------------------------------------------------------------
+void TMainWindow::DoOpen(const char* FileName)
+{
+  /* locals */
+  FILE* CurrentFile; /* Original (don't confuse with temp) SPR file handle keeper*/
+
+  _tempFile.Open(&_tempFile); // Open a new temp file
+
+  CurrentFile = fopen(FileName, "rb"); // Open file
+  if (CurrentFile)
+  {
+    int Result = opensave_OpenFile(CurrentFile, _tempFile.GetStreamPtr(&_tempFile)); /* Actually open the file to the temp file */
+    if (Result != -1) /* Abnormal result? */
+    {
+      /* Problems with file? */
+      LogError(opensave_GetLastError(Result)); /* Shove a message on stderr */
+    }
+    SprFile2Win(CurrentFile); // Copy details from file onto main window
+    fclose(CurrentFile); // Close file again
+  }
+}
+//---------------------------------------------------------------------------
+void TMainWindow::SprFile2Win(FILE* SprFile)
+{
+}
+//---------------------------------------------------------------------------
+/* Open/save works by:
+ Opening the file: Fills the temporary file with a fully expanded header
+ format of the original file.
+
+ Saving the file: Copys the temporary file data into the original
+ filename, possibly ommiting headers if they are not used.
+
+ Language compliance: ANSI C
+*/
+
+#include <StdIO.H> /* For file I/O */
+#include <StdLib.H> /* free() */
+#include "Stds\DLStdInc.H" /* Daybo Logic standard inclusions header */
+#include "DLUtils\DLUtils.H" /* Daybo Logic utilities */
+#pragma hdrstop
+
+#include "CoppsRes.H" /* Main "TheCopps" resource format */
+#include "ResObjWK.H" /* Chain-linked Resource object work */
+#include "SprWork.H" /* Sprite resource-file related work */
+#include "OpenSave.H" /* Our header */
+#include "Headers\AnsiSfnc.H"
+/*-------------------------------------------------------------------------*/
+const int opensave_OpenFile(FILE* File2Open, FILE* TemporaryFile)
+{
+  /* locals */
+  S_RESOBJHEADER ResObjHeader;
+  S_RESSPRITEHEADER ResSpriteHeader;
+  FILE_BLOCK_SIZE fbs; /* For mass sequential data processing */
+  unsigned long looper; /* Looping control */
+  BYTE* Mass; /* Pointer to massive allocated memory (for copying large stuff) */
+
+  /* Check validity of parameters */
+  if (!File2Open || !TemporaryFile) return FALSE;
+
+  if (!fseek(TemporaryFile, 0, SEEK_SET)) return OPENSAVE_ERROR_STREAM; /* Seek to top of temporary file */
+  if (!fseek(File2Open, 0, SEEK_SET)) return OPENSAVE_ERROR_STREAM; /* Seek to top of original file */
+
+  /* Now to read the resource object header */
+  if (!resobjwk_ReadResObjHeader(File2Open, &ResObjHeader, FALSE)) return OPENSAVE_ERROR_EOF;
+
+  /* Now to inspect the contents of that header */
+  if (ResObjHeader.Sig != RESOBJHEADER_SIG) /* Unexpected invalid signature? */
+  {
+    return OPENSAVE_ERROR_OBJBADSIG; /* Bad signature! */
+  }
+  if (ResObjHeader.ResVer < RESOBJHEADER_VER) /* Old version */
+  {
+    return OPENSAVE_ERROR_OBJOLDVER; /* Report old version */
+  }
+  if (ResObjHeader.ResVer > RESOBJHEADER_VER) /* Version made in future! */
+  {
+    return OPENSAVE_ERROR_OBJNEWVER; /* Report future version */
+  }
+
+  /* Let's write the resource object header to the temp file */
+  if (!resobjwk_WriteResObjHeader(TemporaryFile, &ResObjHeader, FALSE)) return OPENSAVE_ERROR_STREAM;
+
+  /* In the original file (File2Open) there might now follow an extended
+  header, full of author related info.  I shall read this into memory and
+  copy it if it exists, we know it exists or not thanks to a field in the
+  resource object header */
+  if (ResObjHeader.IsExt) /* Header is extended? */
+  {
+    BOOL Success;
+    int Fail = 0; /* Fail index for errors, OK by default */
+
+    PS_RESOBJHEADEREX PResObjHeaderEx = (S_RESOBJHEADEREX*)xmalloc( sizeof(S_RESOBJHEADER) ); /* Allocate space in memory */
+    Success = resobjwk_ReadResObjHeaderEx(File2Open, PResObjHeaderEx, FALSE); /* Read into mem from original */
+    if (!Success) /* Failed? */ { Fail = OPENSAVE_ERROR_EOF;  goto CleanupEx; }
+    Success = resobjwk_WriteResObjHeaderEx(TemporaryFile, PResObjHeaderEx, FALSE); /* Write into temp file from mem */
+    if (!Success) /* Failed? */ { Fail = OPENSAVE_ERROR_STREAM; goto CleanupEx; }
+
+CleanupEx:
+    if (!Success) return Fail; /* Give possible failure number */
+    free(PResObjHeaderEx); /* Release transfer memory used to copy extended header */
+  } /* (ResObjHeader.IsExt) */
+
+  if (!ReadSpriteHeader(File2Open, &ResSpriteHeader, FALSE)) return OPENSAVE_ERROR_EOF; /* Read sprite header */
+  if (!WriteSpriteHeader(TemporaryFile, &ResSpriteHeader, FALSE)) return OPENSAVE_ERROR_STREAM; /* Write sprite header */
+
+  /* Now all we need to do is copy the data (the sprite) */
+  CalcFileBlockSize(subst_filelength(File2Open)-ftell(File2Open), &fbs); /* Calculate blocking size for data */
+
+  Mass = xmalloc(fbs.BufferSize); /* Allocate space for copying */
+  for (looper = 0; looper < fbs.Loops; looper++) /* For number of times we need to use the buffer */
+  {
+    fread(Mass, fbs.BufferSize, 1, File2Open); /* Read in data */
+    /* EOF error cannot ocour in input because we know it's size */
+    if (fwrite(Mass, fbs.BufferSize, 1, TemporaryFile) != 1) /* Write data */
+    {
+      /* Error in writing output */
+      free(Mass); /* Free the massive copy buffer */
+      return OPENSAVE_ERROR_STREAM; /* Fail with an error */
+    }
+  }
+  /* All data up to the multiple of the buffer size smaller than the total
+  has been written.  Now a remainder (if present (usually is)) must be copied
+  */
+  if (fbs.Remainder) /* What a suprise, a remainder to write */
+  {
+    fread(Mass, fbs.Remainder, 1, File2Open); /* Read in data */
+    if (fwrite(Mass, fbs.Remainder, 1, TemporaryFile) != 1) /* Write data */
+    {
+      /* Error in writing output */
+      free(Mass); /* Free the massive copy buffer */
+      return OPENSAVE_ERROR_STREAM; /* Fail with an error */
+    }
+  }
+  /* All is said and all is done */
+  free(Mass); /* Release mass copy buffer */
+  return OPENSAVE_ERROR_NOERROR; /* Report success */
+}
+/*-------------------------------------------------------------------------*/
+const int opensave_SaveFile(FILE* File2Save, FILE* TemporaryFile)
+{
+}
+/*-------------------------------------------------------------------------*/
+const char* opensave_GetLastError(const int Index)
+{
+  static const char Msgs[][200] = {
+    "Could not find resource object header at top of file",
+    "SprEd no longer supports this old version, rebuild it from the bitmap",
+    "SprEd cannot support this file, it is too new!  <-- Time for SprEd to be rebuilt",
+    "File I/O error",
+    "End of file encountered in the middle of a header!"
+  };
+
+  if (Index == OPENSAVE_ERROR_NOERROR) /* A normal function return? */
+    return NULL;
+
+  if (Index > OPENSAVE_ERROR_MAXERROR || Index < -2) /* Exceeded max error number? */
+    return NULL;
+
+  return Msgs[Index]; /* Give requested pointer to error message */
+}
+/*-------------------------------------------------------------------------*/
+[directory stream]
+DelayMaxSize=0
+[open]
+Fail=no
+[file handle]
+DelayMaxSize=0
+Functions called:
+ fclose (1 times)
+ DestroyWindow (1 times)
+ GetMenuState (180 times)
+ GetMenuItemCount (90 times)
+ GetMenu (225 times)
+ ShowScrollBar (1 times)
+ GetClientRect (10 times)
+ GetWindowRect (24 times)
+ CreateWindowExA (1 times)
+ LoadMenuA (1 times)
+ RegisterClassA (1 times)
+ sprintf (1 times)
+ freopen (1 times)
+ delete (35 times)
+ free (15 times)
+ strcpy (18 times)
+ new[] (32 times)
+ delete[] (32 times)
+ new (35 times)
+ GetFileType (3 times)
+ calloc (1 times)
+ strlen (68 times)
+ realloc (1 times)
+ GetModuleFileNameA (3 times)
+ malloc (13 times)
+ GetProcAddress (5 times)
+ memcpy (12 times)
+Resource types used:
+ object array (32 allocs, 17 max)
+ object (35 allocs, 33 max)
+ memory block (15 allocs, 13 max)
+ file stream (1 allocs, 1 max)
+ file handle (1 allocs, 1 max)
+Modules used:
+ D:\WINNT\system32\COMDLG32.DLL 00000000 04/29/99 12:04:00
+ D:\WINNT\system32\GDI32.dll 77ED0000 04/29/99 12:04:00
+ D:\WINNT\system32\USER32.dll 00000000 04/29/99 12:04:00
+ D:\BC5\BIN\CG32.DLL 00230000 03/25/97 04:02:00
+ D:\WINNT\system32\KERNEL32.DLL 00000000 04/29/99 12:04:00
+ G:\Projects\GDT\SprEd\spred.exe 003D2CEE 04/29/99 21:47:56
+==========================================
+/* Main module of SprEd */
+#include <OWL\Applicat.H> // Borland TApplication
+#include <String.H>
+#include <StdIO.H>
+#pragma hdrstop
+
+#include "SprEdApp.H" // TSprEdApp class
+//#include "SprEd.H"
+
+//---------------------------------------------------------------------------
+int OwlMain(int, char* [])
+{
+  int RunResult; /* Result from Run() */
+  FILE* ErrStream;
+
+  ErrStream = freopen("Spred.log", "a+t", stderr); /* Redirect errors to a log file */
+  if (ErrStream)
+  {
+    RunResult = TSprEdApp().Run();
+  }
+  else /* Oh-no can't redirect stderr */
+  {
+    MessageBox(GetDesktopWindow(), "SprEd can't redirect errors into SprEd.LOG!", "Error", MB_OK + MB_ICONSTOP);
+    RunResult = 3; /* Bit like abort()'s return */
+  }
+
+  // Cleanup
+  if (ErrStream) fclose(ErrStream); /* Close error stream */
+  return RunResult; /* Give result from framework running */
+}
+//---------------------------------------------------------------------------

SprEd/spred.exe

Binary file added.

SprEd/spred.exe.sig

Binary file added.
+/****************************************************************************
+
+
+spred.rc
+
+produced by Borland Resource Workshop
+
+
+*****************************************************************************/
+
+#include "SprEd.RH"
+
+VERSIONINFO_1 VERSIONINFO 
+FILEVERSION 0, 0, 1, 1
+PRODUCTVERSION 0, 0, 1, 1
+FILEOS VOS_NT_WINDOWS32
+FILETYPE VFT_APP
+{
+ BLOCK "StringFileInfo"
+ {
+  BLOCK "040904E4"
+  {
+   VALUE "CompanyName", "Daybo Logic\000\000"
+   VALUE "FileDescription", ".SPR file editor for compiled sprites\000"
+   VALUE "FileVersion", "0.01\000\000"
+   VALUE "InternalName", "SprEd\000"
+   VALUE "LegalCopyright", "Daybo Logic 1999\000\000"
+   VALUE "OriginalFilename", "SprEd.EXE\000"
+   VALUE "Comments", "When a sprite is compiled to the sprite type used by Daybo Logic (SPR) from a bitmap (BMP) with SPRC, it may be modified with this\000\000"
+   VALUE "Programmer", "David Duncan Ross Palmer\000"
+   VALUE "OS", "Win32 or Win3.1 with Win32s layer\000\000"
+   VALUE "FileType", "Win32 PE (GUI)\000"
+  }
+
+ }
+
+ BLOCK "VarFileInfo"
+ {
+  VALUE "Translation", 0x409, 1252
+ }
+
+}
+
+IDM_MAINMENU MENU 
+{
+ POPUP "&File"
+ {
+  MENUITEM "&Open...", CM_FILEOPEN
+  MENUITEM "&Re-compile", CM_FILECOMPILE
+  MENUITEM SEPARATOR
+  MENUITEM "E&xit", CM_FILEEXIT
+ }
+
+ POPUP "&Help"
+ {
+  MENUITEM "Help &Topics", CM_HELPTOPICS
+  MENUITEM SEPARATOR
+  MENUITEM "&About...", CM_HELPABOUT
+ }
+
+}
+
+
+STRINGTABLE
+{
+ CM_FILEOPEN, "Opens a compiled sprite (.SPR)"
+ CM_FILECOMPILE, "Saves the sprite back (re-compile)"
+ CM_FILEEXIT, "Closes the editor"
+ CM_HELPTOPICS, "See topics which can help you"
+ CM_HELPABOUT, "Title, copyright and version information"
+}
+
+IDI_MAINICON ICON
+{
+ '00 00 01 00 01 00 20 20 10 00 00 00 00 00 E8 02'
+ '00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00'
+ '00 00 01 00 04 00 00 00 00 00 80 02 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 80 00 00 80 00 00 00 80 80 00 80 00'
+ '00 00 80 00 80 00 80 80 00 00 80 80 80 00 C0 C0'
+ 'C0 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00'
+ '00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 88 95'
+ 'DF 80 00 0D 01 0F 00 00 8F D8 BB 85 95 DF 15 58'
+ '8B 5D D0 00 0F 00 00 5F 58 FD D8 9D F9 DF 5D E5'
+ '38 8D DD 00 05 00 0D 59 DD 5D 55 9D 85 D8 DD 83'
+ '59 F8 5D 00 F9 D0 08 99 CD 8F 89 F8 FD 89 58 BD'
+ 'F8 85 35 00 89 F0 0F F5 D5 5D 8B 1D F8 8D 5F 83'
+ 'E5 8D 5F 00 F8 F0 0E 8D DF D8 5D 98 5D FD DF 83'
+ '58 8B 38 00 E5 80 05 85 DF 85 9D 55 5D 88 DF ED'
+ 'D8 88 8F 00 DD 50 0F 85 83 81 58 35 5F 85 5D 88'
+ '58 D8 58 01 8D 81 08 89 85 FC DD 9D 15 5D 5D 95'
+ '95 D8 F8 01 F8 81 08 88 5D 85 DE 5F E5 9D D8 95'
+ '5D F5 F0 00 00 00 00 8B DD 81 D5 DD 88 8D F8 58'
+ '59 55 80 00 00 00 00 D5 DC 1D F5 D8 85 59 89 C5'
+ '51 83 EF 00 00 00 03 D8 F5 5F 5D 8B F5 F8 88 9F'
+ '55 E5 85 00 00 00 08 FF E8 98 DD 85 FD F5 D8 5B'
+ '3D 5D D5 00 00 00 08 55 D8 85 DF 85 88 DD 55 DF'
+ 'CD 98 DD 00 00 00 0F AD F9 88 8F 8B 8F F8 D8 58'
+ 'A8 80 10 01 A1 11 0A AA 8D 95 58 59 DF F9 1C D5'
+ 'A5 B0 10 0A A1 11 00 AD F8 FD D5 DD 88 8D 5C D5'
+ 'AD 80 10 A1 A1 11 00 18 5D 88 5D 8D FF 8F B8 85'
+ 'A8 80 1A A1 A1 11 00 A5 D8 18 5D 85 B5 D8 B5 F8'
+ 'A8 50 1A 01 A1 11 00 A5 D5 59 D8 5D 88 8F 59 88'
+ 'A8 9A AA 01 A1 11 0A AD F8 39 D5 DD 5D 5B 59 8B'
+ 'AC AA 11 11 A1 11 1A AA A9 58 D5 88 F8 D8 58 15'
+ 'A5 A0 00 00 A1 00 00 08 AA A8 CD 88 B5 59 DD 5D'
+ 'AD A0 00 0A A1 00 00 0D 8F A5 DD 38 9D FC 5C 58'
+ 'AA AD 00 0A A1 00 00 5D BA AF 1D 5D F5 5D 9F 5D'
+ 'A1 D8 00 01 A7 70 00 9D A8 5D 88 95 DF DD DF F8'
+ 'B5 55 90 01 A1 10 AA AA 55 C9 8B 89 D8 8D DD 88'
+ '5D FD 50 01 71 70 0D 85 51 58 88 F8 9B 9D 58 88'
+ 'DD 88 5F 00 11 10 0D 88 1D 85 BB F5 D8 DD DF 85'
+ '8D 85 D8 D0 01 00 85 D8 58 5D 85 85 D8 59 DD F8'
+ 'DD DF 8D DD 00 0D DF 8D DD F8 DD DF 8D DD 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+ '00 00 00 00 00 00 00 00 00 00 00 00 00 00'
+}
+
+IDD_ABOUTBOX DIALOG 0, 0, 240, 69
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "About the compiled sprite editor"
+FONT 8, "MS Sans Serif"
+{
+ CONTROL "OK", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 95, 52, 50, 14
+ CONTROL "Technical compiled sprite editor,\nCopyright �1999 Daybo Logic, written by David Duncan Ross Palmer.  First used with TheCopps.\n\nVersion 0.01", IDC_AB_ST, "static", SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE, 36, 4, 196, 44
+ CONTROL IDI_MAINICON, IDC_AB_STPIC, "static", SS_ICON | SS_REALSIZEIMAGE | WS_CHILD | WS_VISIBLE, 8, 8, 21, 20
+}
+
+IDD_MAINWIN DIALOG 0, 0, 217, 132
+STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
+CAPTION ""
+FONT 8, "MS Sans Serif"
+{
+ CONTROL "Resource object header", IDG_RESOBJGRP, "button", BS_GROUPBOX | WS_CHILD | WS_VISIBLE | WS_GROUP, 4, 4, 100, 124
+ CONTROL "Sprite header", IDG_SPRITEGRP, "button", BS_GROUPBOX | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_GROUP, 112, 8, 100, 112
+ CONTROL "SPR_", IDC_RESOBJ_GLBLRESID, "edit", ES_LEFT | ES_AUTOHSCROLL | ES_UPPERCASE | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 8, 24, 92, 12
+ CONTROL "Extended header", IDC_RESOBJ_EXTCHK, "button", BS_3STATE | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 8, 44, 92, 9
+ CONTROL "Resource description:", IDC_STATICTEXT1, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 8, 56, 92, 9
+ CONTROL "", IDC_RESOBJ_RESDESC, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 8, 64, 92, 12
+ CONTROL "Author/Artist:", IDC_STATICTEXT2, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 8, 80, 92, 9
+ CONTROL "", IDC_RESOBJ_AUTHOR, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 8, 88, 92, 12
+ CONTROL "Comments:", IDC_STATICTEXT3, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 8, 104, 92, 9
+ CONTROL "", IDC_RESOBJ_COMMENTS, "edit", ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 8, 112, 92, 12
+ CONTROL "Global resource ID:", IDC_STATICTEXT4, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 8, 13, 92, 9
+ CONTROL "Sprite ID:", IDC_STATICTEXT5, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 116, 16, 92, 9
+ CONTROL "", IDC_SPR_ID, "edit", ES_LEFT | ES_AUTOHSCROLL | ES_UPPERCASE | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 116, 28, 92, 12
+ CONTROL "Member of group", IDC_SPR_GRPMEMCHK, "button", BS_3STATE | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 116, 47, 92, 9
+ CONTROL "Group ID:", IDC_STATICTEXT6, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 116, 60, 92, 9
+ CONTROL "", IDC_SPR_GROUPID, "edit", ES_LEFT | ES_AUTOHSCROLL | ES_UPPERCASE | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 116, 73, 92, 12
+ CONTROL "ComboBox1", IDC_SPR_STDGRPPOS, "combobox", CBS_DROPDOWNLIST | CBS_HASSTRINGS | CBS_UPPERCASE | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_VSCROLL | WS_TABSTOP, 116, 88, 92, 9
+ CONTROL "Checksum:", IDC_STATICTEXT7, "static", SS_LEFTNOWORDWRAP | WS_CHILD | WS_VISIBLE, 116, 103, 92, 9
+ CONTROL "", IDC_SPR_SUM, "edit", ES_LEFT | ES_NUMBER | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_BORDER | WS_TABSTOP, 156, 103, 48, 12
+ CONTROL "", IDC_STATICFRAME1, "static", SS_ETCHEDFRAME | WS_CHILD | WS_VISIBLE, 0, 0, 217, 1
+}
+
+

SprEd/spred.res

Binary file added.

SprEd/spredapp.cpp

+#include <OWL\OwlAll.H>
+#include "Stds\DLStdInc.H" /* Daybo Logic standard inclusions */
+#include "DLStrLib\DLStrLib.H" /* Daybo Logic's String Library */
+#pragma hdrstop
+
+#include "TempFile.H" // Temporary file manager (support)
+#include "SprEd.RHI" // Resource IDs
+#include "SprEdApp.H" // Application class
+#include "MainWnd.H" // Main window class
+//---------------------------------------------------------------------------
+void TSprEdApp::InitMainWindow()
+{
+	SetMainWindow(new TFrameWindow( 0, "Technical compiled sprite editor", new TMainWindow, _TRUE ));
+   GetMainWindow()->AssignMenu(IDM_MAINMENU); // Attach main menu to main window
+   GetMainWindow()->SetIcon(Module, IDI_MAINICON); // Set icon on main window
+   GetMainWindow()->SetStyle(WS_BORDER|WS_CAPTION|WS_MINIMIZEBOX|WS_SYSMENU);
+}
+//---------------------------------------------------------------------------
+/* This is the portable ANSI C section of the technical
+compiled sprite editor.  It is this module which does the
+actual work. */
+/*-------------------------------------------------------------------------*/
+#include <StdIO.h> /* File stream support */
+#include <Assert.H> /* Assertation macro */
+#include <StdLib.H> /* for dynamic allocation and release of heap memory */
+#include "Stds\DLStdInc.H" /* Daybo Logic standard inclusions header */
+#pragma hdrstop
+
+#include "DLUtils\DLUtils.H" /* Daybo Logic utils library support */
+#include "CoppsRes.H" /* Internal resource definitions */
+#include "ResObjWk.H" /* Resource object work */
+#include "SprWork.H" /* Sprite object work */
+#include "SprEdTec.H" /* Our header */
+/*-------------------------------------------------------------------------*/
+//BOOL spredtec_Write(FILE* file, const PS_RESOBJHEADER PResObjHead, const PS_RESOBJHEADEREX PResObjHeadEx, const PS_RESSPRITEHEADER PSpriteHead)
+//{
+//  /* Ensure pointer parameters are safe (but don't assert optional one)*/
+//  assert(file);
+//  assert(PResObjHead);
+//  assert(PSpriteHead);
+//
+//  return TRUE; /* Success */
+//}
+/*-------------------------------------------------------------------------*/
+BOOL spredtec_Read(FILE* file, PS_RESOBJHEADER PResObjHead, PS_RESOBJHEADEREX PResObjHeadEx, PS_RESSPRITEHEADER PSpriteHead)
+{
+  /* locals */
+  long int Origin; /* Position of file pointer before read */
+
+  /* Ensure pointer parameters are safe (but don't assert optional one) */
+  assert(file);
+  assert(PResObjHead);
+  assert(PSpriteHead);
+
+  Origin = ftell(file); /* Save file pointer origin */
+  if (Origin == -1L) /* Error recovering origin */
+  {
+    #ifdef __DAYBO_DEBUGGING__
+    perror("spredtec_Read (recover origin)");
+    #endif /*__DAYBO_DEBUGGING__*/
+    return FALSE;
+  }
+  if (fseek(file, 0x0, SEEK_SET) != 0) /* Seek to top of file */
+  {
+    /* Error in seek to top */
+    #ifdef __DAYBO_DEBUGGING__
+    perror("spredtec_Read (seek to top)");
+    #endif /*__DAYBO_DEBUGGING__*/
+    return FALSE;
+  }
+  if (!resobjwk_ReadResObjHeader(file, PResObjHead, FALSE)) /* Read back resource object header */
+  {
+    /* Couldn't read all of it? */
+    LogError("Not all of resource object header could be read"); /* Log error */
+  }
+  if (PResObjHead->Sig != RESOBJHEADER_SIG) /* Incorrect header signature? */
+  {
+    LogError("Not correct file format"); /* Log error */
+    return FALSE; /* Give up */
+  }
+  if (PResObjHead->ResVer != 2) /* Not the only version we know how to handle? */
+  {
+    LogError("Don\'t know how to handle this resource version!"); /* Log error */
+    return FALSE; /* Give up */
+  }
+  if (PResObjHead->IsExt) /* Extended header? */
+  {
+    if (PResObjHeadEx) /* Caller want's stuff in extended header? */
+    {
+      if (!resobjwk_ReadResObjHeaderEx(file, PResObjHeadEx, FALSE)) /* Read extended header for caller */
+      {
+        /* Failed to read? */
+        LogError("Not all of resource object extended header could be read"); /* Log error */
+      }
+    }
+    else /* Caller doesn't want extended header, even though it's here! */
+    {
+      /* Make our own in memory to bypass it, it's quite large (about 768 at
+      time of writing) and it's safer to put it on the heap incase this is DOS
+      with a 4kb stack. */
+      PS_RESOBJHEADEREX PExHead = (S_RESOBJHEADEREX*)xmalloc(sizeof(S_RESOBJHEADEREX));
+      resobjwk_ReadResObjHeaderEx(file, PExHead, FALSE); /* Read back ext header to move file pointer on */
+      free(PExHead); /* Not actually used apart from to move the file pointer */
+    }
+    /* Now resource header (plus possible extension) is read, it's
+    time for the sprite header */
+    if (PResObjHead->Type != RESOBJTYPE_SPRITE) /* Oops, this is not a sprite */
+    {
+      LogError("File is not a sprite"); /* Log error */
+      return FALSE; /* Give up */
+    }
+    if (!ReadSpriteHeader(file, PSpriteHead, FALSE)) /* Read sprite header */
+    {
+      LogError("Not all of sprite header was read");
+    }
+    /* That's it folks! */
+  }
+
+  return TRUE; /* Success */
+}
+/*-------------------------------------------------------------------------*/

SprEd/tarts.spr

Empty file added.