summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs/wolf3d/id_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/id_pm.c')
-rw-r--r--apps/plugins/sdl/progs/wolf3d/id_pm.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/id_pm.c b/apps/plugins/sdl/progs/wolf3d/id_pm.c
new file mode 100644
index 0000000000..4b8d580b14
--- /dev/null
+++ b/apps/plugins/sdl/progs/wolf3d/id_pm.c
@@ -0,0 +1,125 @@
+#include "wl_def.h"
+
+int ChunksInFile;
+int PMSpriteStart;
+int PMSoundStart;
+
+bool PMSoundInfoPagePadded = false;
+
+// holds the whole VSWAP
+uint32_t *PMPageData;
+size_t PMPageDataSize;
+
+// ChunksInFile+1 pointers to page starts.
+// The last pointer points one byte after the last page.
+uint8_t **PMPages;
+
+void PM_Startup()
+{
+ char fname[13 + sizeof(DATADIR)] = DATADIR "vswap.";
+ strcat(fname,extension);
+
+ FILE *file = fopen(fname,"rb");
+ if(!file)
+ CA_CannotOpen(fname);
+
+ ChunksInFile = 0;
+ fread(&ChunksInFile, sizeof(word), 1, file);
+ PMSpriteStart = 0;
+ fread(&PMSpriteStart, sizeof(word), 1, file);
+ PMSoundStart = 0;
+ fread(&PMSoundStart, sizeof(word), 1, file);
+
+ uint32_t* pageOffsets = (uint32_t *) malloc((ChunksInFile + 1) * sizeof(int32_t));
+ CHECKMALLOCRESULT(pageOffsets);
+ fread(pageOffsets, sizeof(uint32_t), ChunksInFile, file);
+
+ word *pageLengths = (word *) malloc(ChunksInFile * sizeof(word));
+ CHECKMALLOCRESULT(pageLengths);
+ fread(pageLengths, sizeof(word), ChunksInFile, file);
+
+ fseek(file, 0, SEEK_END);
+ long fileSize = ftell(file);
+ long pageDataSize = fileSize - pageOffsets[0];
+ if(pageDataSize > (size_t) -1)
+ Quit("The page file \"%s\" is too large!", fname);
+
+ pageOffsets[ChunksInFile] = fileSize;
+
+ uint32_t dataStart = pageOffsets[0];
+ int i;
+
+ // Check that all pageOffsets are valid
+ for(i = 0; i < ChunksInFile; i++)
+ {
+ if(!pageOffsets[i]) continue; // sparse page
+ if(pageOffsets[i] < dataStart || pageOffsets[i] >= (size_t) fileSize)
+ Quit("Illegal page offset for page %i: %u (filesize: %u)",
+ i, pageOffsets[i], fileSize);
+ }
+
+ // Calculate total amount of padding needed for sprites and sound info page
+ int alignPadding = 0;
+ for(i = PMSpriteStart; i < PMSoundStart; i++)
+ {
+ if(!pageOffsets[i]) continue; // sparse page
+ uint32_t offs = pageOffsets[i] - dataStart + alignPadding;
+ if(offs & 1)
+ alignPadding++;
+ }
+
+ if((pageOffsets[ChunksInFile - 1] - dataStart + alignPadding) & 1)
+ alignPadding++;
+
+ PMPageDataSize = (size_t) pageDataSize + alignPadding;
+ PMPageData = (uint32_t *) malloc(PMPageDataSize);
+ CHECKMALLOCRESULT(PMPageData);
+
+ PMPages = (uint8_t **) malloc((ChunksInFile + 1) * sizeof(uint8_t *));
+ CHECKMALLOCRESULT(PMPages);
+
+ // Load pages and initialize PMPages pointers
+ uint8_t *ptr = (uint8_t *) PMPageData;
+ for(i = 0; i < ChunksInFile; i++)
+ {
+ if(i >= PMSpriteStart && i < PMSoundStart || i == ChunksInFile - 1)
+ {
+ size_t offs = ptr - (uint8_t *) PMPageData;
+
+ // pad with zeros to make it 2-byte aligned
+ if(offs & 1)
+ {
+ *ptr++ = 0;
+ if(i == ChunksInFile - 1) PMSoundInfoPagePadded = true;
+ }
+ }
+
+ PMPages[i] = ptr;
+
+ if(!pageOffsets[i])
+ continue; // sparse page
+
+ // Use specified page length, when next page is sparse page.
+ // Otherwise, calculate size from the offset difference between this and the next page.
+ uint32_t size;
+ if(!pageOffsets[i + 1]) size = pageLengths[i];
+ else size = pageOffsets[i + 1] - pageOffsets[i];
+
+ fseek(file, pageOffsets[i], SEEK_SET);
+ fread(ptr, 1, size, file);
+ ptr += size;
+ }
+
+ // last page points after page buffer
+ PMPages[ChunksInFile] = ptr;
+
+ free(pageLengths);
+ free(pageOffsets);
+ fclose(file);
+}
+
+void PM_Shutdown()
+{
+ free(PMPages);
+ free(PMPageData);
+}