chore: initial commit

This commit is contained in:
fallenoak 2023-01-02 13:17:18 -06:00
commit 70b00c5c38
No known key found for this signature in database
GPG key ID: 7628F8E61AEA070D
965 changed files with 264882 additions and 0 deletions

202
src/gx/texture/CBLPFile.cpp Normal file
View 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;
}

View 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
View 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
View 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

View 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
}

View 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