mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 11:12:29 +00:00
chore: initial commit
This commit is contained in:
commit
70b00c5c38
965 changed files with 264882 additions and 0 deletions
202
src/gx/texture/CBLPFile.cpp
Normal file
202
src/gx/texture/CBLPFile.cpp
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
#include "gx/Texture.hpp"
|
||||
#include "gx/texture/CBLPFile.hpp"
|
||||
#include "util/SFile.hpp"
|
||||
#include <cstring>
|
||||
#include <storm/Error.hpp>
|
||||
#include <storm/Memory.hpp>
|
||||
|
||||
TSGrowableArray<unsigned char> CBLPFile::s_blpFileLoadBuffer;
|
||||
|
||||
void CBLPFile::Close() {
|
||||
this->m_inMemoryImage = nullptr;
|
||||
|
||||
if (this->m_images) {
|
||||
SMemFree(this->m_images, __FILE__, __LINE__, 0x0);
|
||||
}
|
||||
|
||||
this->m_images = nullptr;
|
||||
}
|
||||
|
||||
int32_t CBLPFile::Lock2(const char* fileName, PIXEL_FORMAT format, uint32_t mipLevel, unsigned char* data, uint32_t& stride) {
|
||||
STORM_ASSERT(this->m_inMemoryImage);
|
||||
|
||||
if (mipLevel && (!(this->m_header.hasMips & 0xF) || mipLevel >= this->m_numLevels)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char* mipData = static_cast<unsigned char*>(this->m_inMemoryImage) + this->m_header.mipOffsets[mipLevel];
|
||||
size_t mipSize = this->m_header.mipSizes[mipLevel];
|
||||
|
||||
switch (this->m_header.colorEncoding) {
|
||||
case COLOR_PAL:
|
||||
// TODO
|
||||
return 0;
|
||||
|
||||
case COLOR_DXT:
|
||||
switch (format) {
|
||||
case PIXEL_DXT1:
|
||||
case PIXEL_DXT3:
|
||||
case PIXEL_DXT5:
|
||||
memcpy(data, mipData, mipSize);
|
||||
return 1;
|
||||
|
||||
case PIXEL_ARGB8888:
|
||||
case PIXEL_ARGB1555:
|
||||
case PIXEL_ARGB4444:
|
||||
case PIXEL_RGB565:
|
||||
// TODO
|
||||
return 0;
|
||||
|
||||
case PIXEL_ARGB2565:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
case COLOR_3:
|
||||
memcpy(data, mipData, mipSize);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CBLPFile::LockChain2(const char* fileName, PIXEL_FORMAT format, MipBits*& images, uint32_t mipLevel, int32_t a6) {
|
||||
if (mipLevel && (!(this->m_header.hasMips & 0xF) || mipLevel >= this->m_numLevels)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (images) {
|
||||
if (a6 && (this->m_header.colorEncoding == COLOR_DXT || this->m_header.colorEncoding == COLOR_3)) {
|
||||
if (this->m_header.colorEncoding == COLOR_3 || (format != PIXEL_ARGB4444 && format != PIXEL_RGB565 && format != PIXEL_ARGB1555 && format != PIXEL_ARGB8888)) {
|
||||
uint32_t* offset = this->m_header.mipOffsets;
|
||||
|
||||
for (int32_t i = 0; *offset; offset++, i++) {
|
||||
void* address = static_cast<char*>(this->m_inMemoryImage) + *offset;
|
||||
MipBits* image = static_cast<MipBits*>(address);
|
||||
reinterpret_cast<MipBits**>(images)[i] = image;
|
||||
}
|
||||
|
||||
this->m_inMemoryImage = nullptr;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t v13 = this->m_header.height >> mipLevel;
|
||||
|
||||
if (v13 <= 1) {
|
||||
v13 = 1;
|
||||
}
|
||||
|
||||
uint32_t v14 = this->m_header.width >> mipLevel;
|
||||
|
||||
if (v14 <= 1) {
|
||||
v14 = 1;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// MippedImgSet(format, v14, v13, mipLevel);
|
||||
} else {
|
||||
uint32_t v9 = this->m_header.height >> mipLevel;
|
||||
|
||||
if (v9 <= 1) {
|
||||
v9 = 1;
|
||||
}
|
||||
|
||||
uint32_t v10 = this->m_header.width >> mipLevel;
|
||||
|
||||
if (v10 <= 1) {
|
||||
v10 = 1;
|
||||
}
|
||||
|
||||
images = MippedImgAllocA(format, v10, v9, __FILE__, __LINE__);
|
||||
|
||||
if (!images) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
MipBits** ptr = reinterpret_cast<MipBits**>(images);
|
||||
|
||||
for (int32_t level = mipLevel, i = 0; level < this->m_numLevels; level++, i++) {
|
||||
if (!this->Lock2(fileName, format, level, reinterpret_cast<unsigned char*>(ptr[i]), mipLevel)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_inMemoryImage = nullptr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t CBLPFile::Open(const char* filename, int32_t a3) {
|
||||
if (!filename) {
|
||||
// TODO
|
||||
// nullsub_3();
|
||||
// SErrSetLastError(0x57u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->m_inMemoryImage = nullptr;
|
||||
|
||||
if (this->m_images) {
|
||||
SMemFree(this->m_images, __FILE__, __LINE__, 0);
|
||||
}
|
||||
|
||||
size_t v8 = a3 != 0;
|
||||
|
||||
this->m_images = nullptr;
|
||||
|
||||
SFile* fileptr;
|
||||
|
||||
if (!SFile::OpenEx(nullptr, filename, v8, &fileptr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blpSize = SFile::GetFileSize(fileptr, 0);
|
||||
CBLPFile::s_blpFileLoadBuffer.SetCount(blpSize);
|
||||
|
||||
size_t bytesRead;
|
||||
|
||||
SFile::Read(
|
||||
fileptr,
|
||||
CBLPFile::s_blpFileLoadBuffer.m_data,
|
||||
CBLPFile::s_blpFileLoadBuffer.Count(),
|
||||
&bytesRead,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
SFile::Close(fileptr);
|
||||
|
||||
return this->Source(CBLPFile::s_blpFileLoadBuffer.m_data);
|
||||
}
|
||||
|
||||
int32_t CBLPFile::Source(void* fileBits) {
|
||||
this->m_inMemoryImage = nullptr;
|
||||
|
||||
if (this->m_images) {
|
||||
SMemFree(this->m_images, __FILE__, __LINE__, 0);
|
||||
}
|
||||
|
||||
this->m_images = nullptr;
|
||||
this->m_inMemoryNeedsFree = 0;
|
||||
this->m_inMemoryImage = fileBits;
|
||||
|
||||
memcpy(&this->m_header, fileBits, sizeof(this->m_header));
|
||||
|
||||
if (this->m_header.magic != 0x32504C42 || this->m_header.formatVersion != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->m_header.hasMips & 0xF) {
|
||||
this->m_numLevels = CalcLevelCount(this->m_header.width, this->m_header.height);
|
||||
} else {
|
||||
this->m_numLevels = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
70
src/gx/texture/CBLPFile.hpp
Normal file
70
src/gx/texture/CBLPFile.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#ifndef GX_TEXTURE_C_BLP_FILE_HPP
|
||||
#define GX_TEXTURE_C_BLP_FILE_HPP
|
||||
|
||||
#include "gx/Types.hpp"
|
||||
#include "gx/texture/CGxTex.hpp"
|
||||
#include <cstdint>
|
||||
#include <storm/Array.hpp>
|
||||
|
||||
enum MipMapAlgorithm {
|
||||
MMA_BOX = 0x0,
|
||||
MMA_CUBIC = 0x1,
|
||||
MMA_FULLDFT = 0x2,
|
||||
MMA_KAISER = 0x3,
|
||||
MMA_LINEARLIGHTKAISER = 0x4,
|
||||
};
|
||||
|
||||
struct BlpPalPixel {
|
||||
char b;
|
||||
char g;
|
||||
char r;
|
||||
char pad;
|
||||
};
|
||||
|
||||
class CBLPFile {
|
||||
struct BLPHeader {
|
||||
uint32_t magic;
|
||||
uint32_t formatVersion;
|
||||
char colorEncoding;
|
||||
char alphaSize;
|
||||
char preferredFormat;
|
||||
char hasMips;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t mipOffsets[16];
|
||||
uint32_t mipSizes[16];
|
||||
|
||||
union {
|
||||
BlpPalPixel palette[256];
|
||||
|
||||
struct {
|
||||
uint32_t headerSize;
|
||||
char headerData[1020];
|
||||
} jpeg;
|
||||
} extended;
|
||||
};
|
||||
|
||||
public:
|
||||
// Static variables
|
||||
static TSGrowableArray<unsigned char> s_blpFileLoadBuffer;
|
||||
|
||||
// Member variables
|
||||
MipBits* m_images = nullptr;
|
||||
BLPHeader m_header;
|
||||
void* m_inMemoryImage = nullptr;
|
||||
int32_t m_inMemoryNeedsFree;
|
||||
uint32_t m_numLevels;
|
||||
uint32_t m_quality = 100;
|
||||
void* m_colorMapping;
|
||||
MipMapAlgorithm m_mipMapAlgorithm = MMA_BOX;
|
||||
char* m_lockDecompMem;
|
||||
|
||||
// Member functions
|
||||
void Close(void);
|
||||
int32_t Lock2(const char*, PIXEL_FORMAT, uint32_t, unsigned char*, uint32_t&);
|
||||
int32_t LockChain2(const char*, PIXEL_FORMAT, MipBits*&, uint32_t, int32_t);
|
||||
int32_t Open(const char*, int32_t);
|
||||
int32_t Source(void*);
|
||||
};
|
||||
|
||||
#endif
|
||||
59
src/gx/texture/CGxTex.cpp
Normal file
59
src/gx/texture/CGxTex.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#include "gx/texture/CGxTex.hpp"
|
||||
#include "gx/Gx.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
CGxTexFlags::CGxTexFlags(EGxTexFilter filter, uint32_t wrapU, uint32_t wrapV, uint32_t force, uint32_t generateMipMaps, uint32_t renderTarget, uint32_t maxAnisotropy) {
|
||||
this->m_filter = filter;
|
||||
this->m_wrapU = wrapU;
|
||||
this->m_wrapV = wrapV;
|
||||
this->m_forceMipTracking = force;
|
||||
this->m_generateMipMaps = generateMipMaps;
|
||||
this->m_renderTarget = renderTarget;
|
||||
this->m_maxAnisotropy = std::min(maxAnisotropy, GxCaps()->m_maxTexAnisotropy);
|
||||
|
||||
// TODO
|
||||
this->m_bit13 = 0;
|
||||
this->m_bit14 = 0;
|
||||
this->m_bit15 = 0;
|
||||
}
|
||||
|
||||
bool CGxTexFlags::operator==(const CGxTexFlags& texFlags) {
|
||||
return this->m_filter == texFlags.m_filter
|
||||
&& this->m_wrapU == texFlags.m_wrapU
|
||||
&& this->m_wrapV == texFlags.m_wrapV
|
||||
&& this->m_forceMipTracking == texFlags.m_forceMipTracking
|
||||
&& this->m_generateMipMaps == texFlags.m_generateMipMaps
|
||||
&& this->m_renderTarget == texFlags.m_renderTarget
|
||||
&& this->m_maxAnisotropy == texFlags.m_maxAnisotropy
|
||||
&& this->m_bit13 == texFlags.m_bit13
|
||||
&& this->m_bit14 == texFlags.m_bit14
|
||||
&& this->m_bit15 == texFlags.m_bit15;
|
||||
}
|
||||
|
||||
CGxTex::CGxTex(EGxTexTarget target, uint32_t width, uint32_t height, uint32_t depth, EGxTexFormat format, EGxTexFormat dataFormat, CGxTexFlags flags, void* userArg, void (*userFunc)(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&), const char* name) {
|
||||
this->m_updateRect = { 0, 0, static_cast<int32_t>(height), static_cast<int32_t>(width) };
|
||||
this->m_target = target;
|
||||
this->m_width = width;
|
||||
this->m_height = height;
|
||||
this->m_dataFormat = dataFormat;
|
||||
this->m_format = format;
|
||||
this->m_depth = depth;
|
||||
this->m_userFunc = userFunc;
|
||||
this->m_userArg = userArg;
|
||||
this->m_flags = flags;
|
||||
this->m_apiSpecificData = nullptr;
|
||||
this->m_apiSpecificData2 = nullptr;
|
||||
this->m_needsUpdate = 1;
|
||||
this->m_needsFlagUpdate = 1;
|
||||
this->m_needsCreation = 1;
|
||||
|
||||
// TODO remaining constructor logic
|
||||
}
|
||||
|
||||
float CGxTex::GetHeight() {
|
||||
return this->m_height;
|
||||
}
|
||||
|
||||
float CGxTex::GetWidth() {
|
||||
return this->m_width;
|
||||
}
|
||||
71
src/gx/texture/CGxTex.hpp
Normal file
71
src/gx/texture/CGxTex.hpp
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#ifndef GX_TEXTURE_C_GX_TEX_HPP
|
||||
#define GX_TEXTURE_C_GX_TEX_HPP
|
||||
|
||||
#include "gx/Types.hpp"
|
||||
#include <cstdint>
|
||||
#include <tempest/Rect.hpp>
|
||||
|
||||
class CGxTexFlags {
|
||||
public:
|
||||
// Member variables
|
||||
uint32_t m_filter : 3;
|
||||
uint32_t m_wrapU : 1;
|
||||
uint32_t m_wrapV : 1;
|
||||
uint32_t m_forceMipTracking : 1;
|
||||
uint32_t m_generateMipMaps : 1;
|
||||
uint32_t m_renderTarget : 1;
|
||||
uint32_t m_maxAnisotropy : 5;
|
||||
uint32_t m_bit13 : 1;
|
||||
uint32_t m_bit14 : 1;
|
||||
uint32_t m_bit15 : 1;
|
||||
|
||||
// Member functions
|
||||
CGxTexFlags()
|
||||
: CGxTexFlags(GxTex_Linear, 0, 0, 0, 0, 0, 1)
|
||||
{};
|
||||
CGxTexFlags(EGxTexFilter, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
bool operator==(const CGxTexFlags& texFlags);
|
||||
};
|
||||
|
||||
class CGxTexParms {
|
||||
public:
|
||||
// Member variables
|
||||
EGxTexTarget target;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth;
|
||||
EGxTexFormat format;
|
||||
EGxTexFormat dataFormat;
|
||||
CGxTexFlags flags = CGxTexFlags(GxTex_Linear, 0, 0, 0, 0, 0, 1);
|
||||
void* userArg;
|
||||
void (*userFunc)(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&);
|
||||
};
|
||||
|
||||
class CGxTex {
|
||||
public:
|
||||
// Member variables
|
||||
CiRect m_updateRect = { 0, 0, 0, 0 };
|
||||
int16_t m_updatePlaneMin = -1;
|
||||
int16_t m_updatePlaneMax = -1;
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
uint32_t m_depth;
|
||||
EGxTexTarget m_target;
|
||||
EGxTexFormat m_format;
|
||||
EGxTexFormat m_dataFormat;
|
||||
CGxTexFlags m_flags = CGxTexFlags(GxTex_Linear, 0, 0, 0, 0, 0, 1);
|
||||
void* m_userArg;
|
||||
void (*m_userFunc)(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&);
|
||||
void* m_apiSpecificData;
|
||||
void* m_apiSpecificData2; // invented name
|
||||
uint8_t m_needsUpdate;
|
||||
uint8_t m_needsCreation;
|
||||
uint8_t m_needsFlagUpdate;
|
||||
|
||||
// Member functions
|
||||
CGxTex(EGxTexTarget, uint32_t, uint32_t, uint32_t, EGxTexFormat, EGxTexFormat, CGxTexFlags, void*, void (*)(EGxTexCommand, uint32_t, uint32_t, uint32_t, uint32_t, void*, uint32_t&, const void*&), const char*);
|
||||
float GetHeight(void);
|
||||
float GetWidth(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
29
src/gx/texture/CTexture.cpp
Normal file
29
src/gx/texture/CTexture.cpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include "gx/texture/CTexture.hpp"
|
||||
#include "gx/Texture.hpp"
|
||||
|
||||
EGxTexFilter CTexture::s_filterMode = GxTex_LinearMipNearest;
|
||||
int32_t CTexture::s_maxAnisotropy = 1;
|
||||
|
||||
bool HASHKEY_TEXTUREFILE::operator==(const HASHKEY_TEXTUREFILE& key) {
|
||||
if (!SStrCmpI(this->m_filename, key.m_filename, STORM_MAX_PATH) && this->m_texFlags == key.m_texFlags) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CTexture::CTexture() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
CTexture::~CTexture() {
|
||||
if (this->gxTex) {
|
||||
TextureFreeGxTex(this->gxTex);
|
||||
}
|
||||
|
||||
if (this->atlas) {
|
||||
// TODO this->atlas->Free(this);
|
||||
}
|
||||
|
||||
// TODO
|
||||
}
|
||||
52
src/gx/texture/CTexture.hpp
Normal file
52
src/gx/texture/CTexture.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef GX_TEXTURE_C_TEXTURE_HPP
|
||||
#define GX_TEXTURE_C_TEXTURE_HPP
|
||||
|
||||
#include "async/AsyncFile.hpp"
|
||||
#include "gx/Types.hpp"
|
||||
#include "gx/texture/CGxTex.hpp"
|
||||
#include "util/CStatus.hpp"
|
||||
#include <cstdint>
|
||||
#include <common/Handle.hpp>
|
||||
#include <storm/Hash.hpp>
|
||||
|
||||
class HASHKEY_TEXTUREFILE {
|
||||
public:
|
||||
// Member variables
|
||||
char* m_filename;
|
||||
CGxTexFlags m_texFlags;
|
||||
|
||||
// Member functions
|
||||
bool operator==(const HASHKEY_TEXTUREFILE&);
|
||||
};
|
||||
|
||||
class CTexture : public CHandleObject, public TSHashObject<CTexture, HASHKEY_TEXTUREFILE> {
|
||||
public:
|
||||
// Static variables
|
||||
static EGxTexFilter s_filterMode;
|
||||
static int32_t s_maxAnisotropy;
|
||||
|
||||
// Member variables
|
||||
uint32_t unk1;
|
||||
uint16_t flags = 0;
|
||||
uint8_t bestMip = 0;
|
||||
uint8_t alphaBits = 0;
|
||||
CStatus loadStatus;
|
||||
CAsyncObject* asyncObject = nullptr;
|
||||
CGxTex* gxTex = nullptr;
|
||||
EGxTexTarget gxTexTarget = GxTex_2d;
|
||||
uint16_t gxWidth = 0;
|
||||
uint16_t gxHeight = 0;
|
||||
EGxTexFormat gxTexFormat = GxTex_Unknown;
|
||||
EGxTexFormat dataFormat = GxTex_Unknown;
|
||||
CGxTexFlags gxTexFlags = CGxTexFlags(GxTex_Linear, 0, 0, 0, 0, 0, 1);
|
||||
void* atlas = nullptr; // TODO CTextureAtlas
|
||||
int32_t atlasBlockIndex = 0;
|
||||
uint32_t unk2[2];
|
||||
char filename[260];
|
||||
|
||||
// Member functions
|
||||
CTexture();
|
||||
~CTexture();
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue