-
Notifications
You must be signed in to change notification settings - Fork 324
/
SkyFile.cs
255 lines (214 loc) · 8.08 KB
/
SkyFile.cs
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
// Project: Daggerfall Unity
// Copyright: Copyright (C) 2009-2023 Daggerfall Workshop
// Web Site: http://www.dfworkshop.net
// License: MIT License (http://www.opensource.org/licenses/mit-license.php)
// Source Code: https://github.com/Interkarma/daggerfall-unity
// Original Author: Gavin Clayton (interkarma@dfworkshop.net)
// Contributors:
//
// Notes:
//
#region Using Statements
using System;
using System.IO;
using DaggerfallConnect.Utility;
#endregion
namespace DaggerfallConnect.Arena2
{
/// <summary>
/// Connects to a SKY??.DAT file to enumerate and extract image data.
/// </summary>
public class SkyFile : BaseImageFile
{
#region Class Variables
// Class constants
private const int frameWidth = 512;
private const int frameHeight = 220;
private const int frameDataLength = frameWidth * frameHeight;
//private const int paletteDataLength = 776;
private const long paletteDataPosition = 0;
private const long imageDataPosition = 549120;
/// <summary>
/// Palette array.
/// </summary>
private readonly DFPalette[] palettes = new DFPalette[32];
/// <summary>
/// Bitmap array.
/// </summary>
private readonly DFBitmap[] bitmaps = new DFBitmap[64];
#endregion
#region Constructors
/// <summary>
/// Default constructor.
/// </summary>
public SkyFile()
{
}
/// <summary>
/// Load constructor.
/// </summary>
/// <param name="filePath">Absolute path to SKY??.DAT file.</param>
/// <param name="usage">Specify if file will be accessed from disk, or loaded into RAM.</param>
/// <param name="readOnly">File will be read-only if true, read-write if false.</param>
public SkyFile(string filePath, FileUsage usage, bool readOnly)
{
Load(filePath, usage, readOnly);
}
#endregion
#region Public Properties
/// <summary>
/// Number of records in this Sky file. Always 2 for a SKY file (one animation each for east and west sky).
/// </summary>
public override int RecordCount
{
get
{
if (managedFile.FilePath == string.Empty)
return 0;
else
return 2;
}
}
/// <summary>
/// SKY files are fully palettized per frame.
/// This method always returns string.Empty and is implemented only to satisfy abstract base class DFImage.
/// Use GetDFPalette(Frame) instead.
/// </summary>
public override string PaletteName
{
get { return string.Empty; }
}
/// <summary>
/// Description of this file (always "SKY File" as the game files contain no text descriptions for this file type).
/// </summary>
public override string Description
{
get { return "SKY File"; }
}
#endregion
#region Public Methods
/// <summary>
/// Loads a SKY file.
/// </summary>
/// <param name="filePath">Absolute path to SKY??.DAT file</param>
/// <param name="usage">Specify if file will be accessed from disk, or loaded into RAM.</param>
/// <param name="readOnly">File will be read-only if true, read-write if false.</param>
/// <returns>True if successful, otherwise false.</returns>
public override bool Load(string filePath, FileUsage usage, bool readOnly)
{
// Exit if this file already loaded
if (managedFile.FilePath == filePath)
return true;
// Validate filename
string fn = Path.GetFileName(filePath);
if (!fn.StartsWith("SKY", StringComparison.InvariantCultureIgnoreCase) &&
!fn.EndsWith(".DAT", StringComparison.InvariantCultureIgnoreCase))
return false;
// Load file
if (!managedFile.Load(filePath, usage, readOnly))
return false;
return true;
}
/// <summary>
/// Gets palette data for specified record and frame.
/// </summary>
/// <param name="frame">Index of frame.</param>
/// <returns>DFPalette object or null.</returns>
public DFPalette GetDFPalette(int frame)
{
// Validate
if (frame < 0 || frame >= 32)
return null;
// Read palette data
ReadPalette(frame);
return palettes[frame];
}
/// <summary>
/// Gets bitmap data as indexed 8-bit byte array.
/// </summary>
/// <param name="record">Index of record.</param>
/// <param name="frame">Index of frame.</param>
/// <returns>DFBitmap object. Check DFBitmap.Data for null on failure.</returns>
public override DFBitmap GetDFBitmap(int record, int frame)
{
// Validate
if (record < 0 || record > 1 || frame < 0 || frame > 31)
return new DFBitmap();
// Calculate index
int Index = record * 32 + frame;
// Read image data
ReadImageData(Index);
return bitmaps[Index];
}
/// <summary>
/// Gets number of frames in specified record. Always 32 for SKY files.
/// </summary>
/// <param name="record">Index of record.</param>
/// <returns>Number of frames or -1 on error.</returns>
public override int GetFrameCount(int record)
{
// Validate
if (string.IsNullOrEmpty(managedFile.FileName) || record < 0 || record >= 2)
return -1;
return 32;
}
/// <summary>
/// Gets width and height of specified record. All frames of this record are the same dimensions.
/// </summary>
/// <param name="record">Index of record.</param>
/// <returns>Size object.</returns>
public override DFSize GetSize(int record)
{
// Validate
if (string.IsNullOrEmpty(managedFile.FileName) || record < 0 || record >= 2)
return new DFSize(0, 0);
return new DFSize(frameWidth, frameHeight);
}
#endregion
#region Static Methods
/// <summary>
/// Returns a SKY??.DAT filename based on index.
/// If the index is not valid, the returned filename will also be invalid.
/// </summary>
/// <param name="skyIndex">Index of sky archive.</param>
/// <returns>Texture filename in the format SKY??.DAT.</returns>
public static string IndexToFileName(int skyIndex)
{
return string.Format("SKY{0:00}.DAT", skyIndex);
}
#endregion
#region Private Methods
/// <summary>
/// Read palette for specified record.
/// </summary>
/// <param name="index">Index of palette.</param>
private void ReadPalette(int index)
{
// Read palette data if not already stored
if (null == palettes[index])
{
BinaryReader Reader = managedFile.GetReader(paletteDataPosition + (776 * index) + 8);
palettes[index] = new DFPalette();
palettes[index].Read(ref Reader);
}
}
/// <summary>
/// Reads image data.
/// </summary>
/// <param name="index">Index of image.</param>
private bool ReadImageData(int index)
{
// Read image if not already stored
if (null == bitmaps[index])
{
BinaryReader Reader = managedFile.GetReader(imageDataPosition + (frameDataLength * index));
bitmaps[index] = new DFBitmap();
bitmaps[index].Width = frameWidth;
bitmaps[index].Height = frameHeight;
bitmaps[index].Data = Reader.ReadBytes(frameDataLength);
}
return true;
}
#endregion
}
}