aboutsummaryrefslogtreecommitdiff
path: root/src/dtx/dtx.cpp
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2025-12-04 13:58:02 +0100
committerXavier Del Campo Romero <xavi92@disroot.org>2025-12-15 23:04:39 +0100
commit600ff28dd73f2cf17725382b68a4b1b2573f2e34 (patch)
treea105c686458d8998438652aeca6299cf9000edcd /src/dtx/dtx.cpp
First commitHEADabcmain
Diffstat (limited to 'src/dtx/dtx.cpp')
-rw-r--r--src/dtx/dtx.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/dtx/dtx.cpp b/src/dtx/dtx.cpp
new file mode 100644
index 0000000..463bb1d
--- /dev/null
+++ b/src/dtx/dtx.cpp
@@ -0,0 +1,207 @@
+#include <dtx.h>
+#include <rez/file.h>
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <cstdint>
+#include <cstdio>
+#include <iostream>
+
+int dtx::draw() const
+{
+ int ret = 0;
+ GLenum error;
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ if (bpp == bpp_s3tc_dxt5)
+ {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+ }
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-0.5f, 0.5f);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(0.5f, 0.5f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(0.5f, -0.5f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(-0.5f, -0.5f);
+ glEnd();
+
+ glFlush();
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+
+ while ((error = glGetError()) != GL_NO_ERROR)
+ {
+ ret = -1;
+ fprintf(stderr, "%s:%d: glGetError returned %x\n", __FILE__,
+ __LINE__, error);
+ }
+
+ return ret;
+}
+
+int dtx::parse(rez::file &f)
+{
+ uint32_t restype, uversion;
+
+ if (f.read_le(restype) || f.read_le(uversion))
+ return -1;
+
+ const uint32_t exp_type = 0;
+ const int32_t exp_version = -5;
+ int32_t version = uversion;
+
+ if (restype != exp_type)
+ {
+ std::cerr << f.path() << ": invalid resource type " << restype
+ << ", expected " << exp_type << '\n';
+ return -1;
+ }
+ else if (version != exp_version)
+ {
+ std::cerr << f.path() << ": invalid or unsupported version " << version
+ << ", expected " << exp_version << '\n';
+ return -1;
+ }
+
+ const uint16_t max_mipmaps = 8;
+ uint16_t w, h, n_mipmaps, n_sections, tex_angle;
+ uint32_t iflags, userflags, tex_scale;
+ unsigned char tex_group, n_rtmipmaps, bpp, mipmap_off_nc, mipmap_off,
+ tex_prio;
+ char cmd[128];
+
+ if (f.read_le(w)
+ || f.read_le(h)
+ || f.read_le(n_mipmaps)
+ || f.read_le(n_sections))
+ {
+ std::cerr << f.path() << ": failed to read header\n";
+ return -1;
+ }
+ else if (!n_mipmaps || n_mipmaps > max_mipmaps)
+ {
+ std::cerr << f.path() << ": invalid number of mipmaps: "
+ << n_mipmaps << '\n';
+ return -1;
+ }
+ else if (f.read_le(iflags) || f.read_le(userflags))
+ {
+ std::cerr << f.path() << ": failed to read flags\n";
+ return -1;
+ }
+ else if (f.read(tex_group)
+ || f.read(n_rtmipmaps)
+ || f.read(bpp)
+ || f.read(mipmap_off_nc)
+ || f.read(mipmap_off)
+ || f.read(tex_prio)
+ || f.read_le(tex_scale)
+ || f.read_le(tex_angle))
+ {
+ std::cerr << f.path() << ": failed to read extra data\n";
+ return -1;
+ }
+ else if (bpp != bpp::bpp_32
+ && bpp != bpp::bpp_s3tc_dxt1
+ && bpp != bpp::bpp_s3tc_dxt5)
+ {
+ std::cerr << f.path() << ": invalid or unsupported bpp "
+ << std::to_string(bpp) << ", expected " << bpp::bpp_s3tc_dxt1
+ << ", " << bpp::bpp_32 << " or " << bpp::bpp_s3tc_dxt5 << '\n';
+ return -1;
+ }
+ else if (f.read(cmd, sizeof cmd))
+ {
+ std::cerr << f.path() << ": failed to read cmd\n";
+ return -1;
+ }
+
+ this->bpp = static_cast<enum bpp>(bpp);
+ this->w = w;
+ this->h = h;
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ GLint level = 0;
+
+ for (uint32_t i = 0; i < n_mipmaps; i++)
+ {
+ GLenum format;
+ unsigned long n_pix = (w >> i) * (h >> i);
+ pixdata mipmap;
+
+ switch (this->bpp)
+ {
+ case bpp_32:
+ format = GL_BGRA;
+ n_pix *= sizeof (uint32_t);
+ break;
+
+ case bpp_s3tc_dxt1:
+ format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ n_pix >>= 1;
+ break;
+
+ case bpp_s3tc_dxt5:
+ format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+
+ default:
+ return -1;
+ }
+
+ mipmap.reserve(n_pix);
+
+ while (n_pix)
+ {
+ unsigned char buf[BUFSIZ];
+ size_t n = n_pix > sizeof buf ? sizeof buf : n_pix;
+
+ if (f.read(buf, n))
+ return -1;
+
+ mipmap.insert(mipmap.end(), buf, &buf[n]);
+ n_pix -= n;
+ }
+
+ GLenum error;
+ int ret = 0;
+
+ if (bpp == bpp::bpp_s3tc_dxt1 || bpp == bpp::bpp_s3tc_dxt5)
+ glCompressedTexImage2D(GL_TEXTURE_2D, level++, format,
+ w >> i, h >> i, 0, mipmap.size(), mipmap.data());
+ else if (bpp == bpp::bpp_32)
+ glTexImage2D(GL_TEXTURE_2D, level++, format, w >> i, h >> i, 0,
+ format, GL_UNSIGNED_BYTE, mipmap.data());
+
+ while ((error = glGetError()) != GL_NO_ERROR)
+ {
+ fprintf(stderr, "%s:%d: glGetError returned %x\n", __FILE__,
+ __LINE__, error);
+ ret = -1;
+ }
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+dtx::~dtx()
+{
+ if (texture)
+ glDeleteTextures(1, &texture);
+}
+
+dtx::dtx() :
+ texture(0)
+{
+}