Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor palette IO and storage #545

Merged
merged 15 commits into from
Sep 16, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class EMImportTextureFunction : BaseEMFunction
public override void ApplyToLevel(TR1Level level)
{
using BitmapGraphics bg = new(new Bitmap(Bitmap));
List<Color> palette = level.Palette.Select(c => Color.FromArgb(c.Red * 4, c.Green * 4, c.Blue * 4)).ToList();
List<Color> palette = level.Palette.Select(c => c.ToColor()).ToList();
Rectangle size = new(0, 0, bg.Bitmap.Width, bg.Bitmap.Height);
bg.Scan(size, (c, x, y) =>
{
Expand All @@ -26,7 +26,7 @@ public override void ApplyToLevel(TR1Level level)
}
else
{
colIndex = TR1PaletteManager.FindClosestColour(c, palette);
colIndex = TRPalette8Control.FindClosestColour(c, palette);
c = palette[colIndex];
}

Expand Down
45 changes: 6 additions & 39 deletions TRLevelControl/Control/TR1LevelControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace TRLevelControl;

public class TR1LevelControl : TRLevelControlBase<TR1Level>
{
private const uint MAX_PALETTE_SIZE = 256;

protected override TR1Level CreateLevel(TRFileVersion version)
{
TR1Level level = new()
Expand Down Expand Up @@ -286,15 +284,8 @@ protected override void Read(TRLevelReader reader)
_level.Entities[i] = TRFileReadUtilities.ReadEntity(reader);
}

//Light Map - 32 * 256 = 8192 bytes
_level.LightMap = new byte[32 * 256];

for (int i = 0; i < _level.LightMap.Length; i++)
{
_level.LightMap[i] = reader.ReadByte();
}

_level.Palette = PopulateColourPalette(reader.ReadBytes((int)MAX_PALETTE_SIZE * 3));
_level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize));
_level.Palette = reader.ReadColours(TRConsts.PaletteSize);

//Cinematic Frames
_level.NumCinematicFrames = reader.ReadUInt16();
Expand Down Expand Up @@ -410,8 +401,10 @@ protected override void Write(TRLevelWriter writer)
writer.Write(_level.NumEntities);
foreach (TREntity entity in _level.Entities) { writer.Write(entity.Serialize()); }

writer.Write(_level.LightMap);
foreach (TRColour col in _level.Palette) { writer.Write(col.Serialize()); }
Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize);
Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize);
writer.Write(_level.LightMap.ToArray());
writer.Write(_level.Palette);

writer.Write(_level.NumCinematicFrames);
foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); }
Expand All @@ -428,32 +421,6 @@ protected override void Write(TRLevelWriter writer)
foreach (uint index in _level.SampleIndices) { writer.Write(index); }
}

private static TRColour[] PopulateColourPalette(byte[] palette)
{
TRColour[] colourPalette = new TRColour[MAX_PALETTE_SIZE];

int ci = 0;

for (int i = 0; i < MAX_PALETTE_SIZE; i++)
{
TRColour col = new()
{
Red = palette[ci]
};
ci++;

col.Green = palette[ci];
ci++;

col.Blue = palette[ci];
ci++;

colourPalette[i] = col;
}

return colourPalette;
}

private static TRRoomData ConvertToRoomData(TRRoom room)
{
int RoomDataOffset = 0;
Expand Down
81 changes: 10 additions & 71 deletions TRLevelControl/Control/TR2LevelControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace TRLevelControl;

public class TR2LevelControl : TRLevelControlBase<TR2Level>
{
private const uint MAX_PALETTE_SIZE = 256;

protected override TR2Level CreateLevel(TRFileVersion version)
{
TR2Level level = new()
Expand All @@ -25,10 +23,9 @@ protected override TR2Level CreateLevel(TRFileVersion version)

protected override void Read(TRLevelReader reader)
{
//Colour palettes and textures
_level.Palette = PopulateColourPalette(reader.ReadBytes((int)MAX_PALETTE_SIZE * 3));

_level.Palette16 = PopulateColourPalette16(reader.ReadBytes((int)MAX_PALETTE_SIZE * 4));
// Colour palettes and textures
_level.Palette = reader.ReadColours(TRConsts.PaletteSize);
_level.Palette16 = reader.ReadColour4s(TRConsts.PaletteSize);

uint numImages = reader.ReadUInt32();
_level.Images8 = reader.ReadImage8s(numImages);
Expand Down Expand Up @@ -298,13 +295,7 @@ protected override void Read(TRLevelReader reader)
_level.Entities[i] = TR2FileReadUtilities.ReadEntity(reader);
}

//Light Map - 32 * 256 = 8192 bytes
_level.LightMap = new byte[32 * 256];

for (int i = 0; i < _level.LightMap.Length; i++)
{
_level.LightMap[i] = reader.ReadByte();
}
_level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize));

//Cinematic Frames
_level.NumCinematicFrames = reader.ReadUInt16();
Expand Down Expand Up @@ -352,8 +343,10 @@ protected override void Read(TRLevelReader reader)

protected override void Write(TRLevelWriter writer)
{
foreach (TRColour col in _level.Palette) { writer.Write(col.Serialize()); }
foreach (TRColour4 col in _level.Palette16) { writer.Write(col.Serialize()); }
Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize);
Debug.Assert(_level.Palette16.Count == TRConsts.PaletteSize);
writer.Write(_level.Palette);
writer.Write(_level.Palette16);

Debug.Assert(_level.Images8.Count == _level.Images16.Count);
writer.Write((uint)_level.Images8.Count);
Expand Down Expand Up @@ -415,7 +408,8 @@ protected override void Write(TRLevelWriter writer)
writer.Write(_level.NumEntities);
foreach (TR2Entity entity in _level.Entities) { writer.Write(entity.Serialize()); }

writer.Write(_level.LightMap);
Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize);
writer.Write(_level.LightMap.ToArray());

writer.Write(_level.NumCinematicFrames);
foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); }
Expand All @@ -430,61 +424,6 @@ protected override void Write(TRLevelWriter writer)
foreach (uint index in _level.SampleIndices) { writer.Write(index); }
}

private static TRColour[] PopulateColourPalette(byte[] palette)
{
TRColour[] colourPalette = new TRColour[MAX_PALETTE_SIZE];

int ci = 0;

for (int i = 0; i < MAX_PALETTE_SIZE; i++)
{
TRColour col = new()
{
Red = palette[ci]
};
ci++;

col.Green = palette[ci];
ci++;

col.Blue = palette[ci];
ci++;

colourPalette[i] = col;
}

return colourPalette;
}

private static TRColour4[] PopulateColourPalette16(byte[] palette)
{
TRColour4[] colourPalette = new TRColour4[MAX_PALETTE_SIZE];

int ci = 0;

for (int i = 0; i < MAX_PALETTE_SIZE; i++)
{
TRColour4 col = new()
{
Red = palette[ci]
};
ci++;

col.Green = palette[ci];
ci++;

col.Blue = palette[ci];
ci++;

col.Unused = palette[ci];
ci++;

colourPalette[i] = col;
}

return colourPalette;
}

private static TR2RoomData ConvertToRoomData(TR2Room room)
{
int RoomDataOffset = 0;
Expand Down
81 changes: 10 additions & 71 deletions TRLevelControl/Control/TR3LevelControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ namespace TRLevelControl;

public class TR3LevelControl : TRLevelControlBase<TR3Level>
{
private const uint MAX_PALETTE_SIZE = 256;

protected override TR3Level CreateLevel(TRFileVersion version)
{
TR3Level level = new()
Expand All @@ -25,10 +23,9 @@ protected override TR3Level CreateLevel(TRFileVersion version)

protected override void Read(TRLevelReader reader)
{
//Colour palettes and textures
_level.Palette = PopulateColourPalette(reader.ReadBytes((int)MAX_PALETTE_SIZE * 3));

_level.Palette16 = PopulateColourPalette16(reader.ReadBytes((int)MAX_PALETTE_SIZE * 4));
// Colour palettes and textures
_level.Palette = reader.ReadColours(TRConsts.PaletteSize);
_level.Palette16 = reader.ReadColour4s(TRConsts.PaletteSize);

uint numImages = reader.ReadUInt32();
_level.Images8 = reader.ReadImage8s(numImages);
Expand Down Expand Up @@ -300,13 +297,7 @@ protected override void Read(TRLevelReader reader)
_level.Entities[i] = TR2FileReadUtilities.ReadEntity(reader);
}

//Light Map - 32 * 256 = 8192 bytes
_level.LightMap = new byte[32 * 256];

for (int i = 0; i < _level.LightMap.Length; i++)
{
_level.LightMap[i] = reader.ReadByte();
}
_level.LightMap = new(reader.ReadBytes(TRConsts.LightMapSize));

//Cinematic Frames
_level.NumCinematicFrames = reader.ReadUInt16();
Expand Down Expand Up @@ -354,8 +345,10 @@ protected override void Read(TRLevelReader reader)

protected override void Write(TRLevelWriter writer)
{
foreach (TRColour col in _level.Palette) { writer.Write(col.Serialize()); }
foreach (TRColour4 col in _level.Palette16) { writer.Write(col.Serialize()); }
Debug.Assert(_level.Palette.Count == TRConsts.PaletteSize);
Debug.Assert(_level.Palette16.Count == TRConsts.PaletteSize);
writer.Write(_level.Palette);
writer.Write(_level.Palette16);

Debug.Assert(_level.Images8.Count == _level.Images16.Count);
writer.Write((uint)_level.Images8.Count);
Expand Down Expand Up @@ -418,7 +411,8 @@ protected override void Write(TRLevelWriter writer)
writer.Write(_level.NumEntities);
foreach (TR2Entity entity in _level.Entities) { writer.Write(entity.Serialize()); }

writer.Write(_level.LightMap);
Debug.Assert(_level.LightMap.Count == TRConsts.LightMapSize);
writer.Write(_level.LightMap.ToArray());

writer.Write(_level.NumCinematicFrames);
foreach (TRCinematicFrame cineframe in _level.CinematicFrames) { writer.Write(cineframe.Serialize()); }
Expand All @@ -433,61 +427,6 @@ protected override void Write(TRLevelWriter writer)
foreach (uint index in _level.SampleIndices) { writer.Write(index); }
}

private static TRColour[] PopulateColourPalette(byte[] palette)
{
TRColour[] colourPalette = new TRColour[MAX_PALETTE_SIZE];

int ci = 0;

for (int i = 0; i < MAX_PALETTE_SIZE; i++)
{
TRColour col = new()
{
Red = palette[ci]
};
ci++;

col.Green = palette[ci];
ci++;

col.Blue = palette[ci];
ci++;

colourPalette[i] = col;
}

return colourPalette;
}

private static TRColour4[] PopulateColourPalette16(byte[] palette)
{
TRColour4[] colourPalette = new TRColour4[MAX_PALETTE_SIZE];

int ci = 0;

for (int i = 0; i < MAX_PALETTE_SIZE; i++)
{
TRColour4 col = new()
{
Red = palette[ci]
};
ci++;

col.Green = palette[ci];
ci++;

col.Blue = palette[ci];
ci++;

col.Unused = palette[ci];
ci++;

colourPalette[i] = col;
}

return colourPalette;
}

private static TR3RoomData ConvertToRoomData(TR3Room room)
{
int RoomDataOffset = 0;
Expand Down
4 changes: 4 additions & 0 deletions TRLevelControl/Helpers/TRConsts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ public static class TRConsts
public const int TPageWidth = 256;
public const int TPageHeight = 256;
public const int TPageSize = TPageWidth * TPageHeight;

public const int PaletteSize = 256;
public const int Palette8Multiplier = 4;
public const int LightMapSize = PaletteSize * 32;
}
31 changes: 31 additions & 0 deletions TRLevelControl/IO/TRLevelReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,35 @@ public List<TRTexImage32> ReadImage32s(long numImages)
}
return images;
}

public List<TRColour> ReadColours(long numColours)
{
List<TRColour> colours = new((int)numColours);
for (long i = 0; i < numColours; i++)
{
colours.Add(new()
{
Red = ReadByte(),
Green = ReadByte(),
Blue = ReadByte()
});
}
return colours;
}

public List<TRColour4> ReadColour4s(long numColours)
{
List<TRColour4> colours = new((int)numColours);
for (long i = 0; i < numColours; i++)
{
colours.Add(new()
{
Red = ReadByte(),
Green = ReadByte(),
Blue = ReadByte(),
Alpha = ReadByte()
});
}
return colours;
}
}
Loading