forked from KS-Presto/Wolf4SDL
-
Notifications
You must be signed in to change notification settings - Fork 0
/
id_pm.cpp
125 lines (99 loc) · 3.14 KB
/
id_pm.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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] = "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);
}