port: EterImageLib Image/TGAImage/DXTCImage verbatim (+ d3d.h ddraw shim)
-fno-strict-aliasing on the port targets: 40250 relies on MSVC's lack of type-based alias analysis (DXTCImage reads Color8888 through DWORD*). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
32c5a09d6e
commit
75ea2703c6
@@ -622,3 +622,6 @@
|
||||
{"date": "2026-09-30", "unit": "EterLib/MSWindow.cpp", "action": "port", "evidence": "verbatim over new winuser.h shim (platform/Win32User.cpp); 64-bit pointer casts ADAPTED; port.ms_window"}
|
||||
{"date": "2026-09-30", "unit": "EterLib/MSApplication.cpp", "action": "port", "evidence": "verbatim over new winuser.h shim (platform/Win32User.cpp); 64-bit pointer casts ADAPTED; port.ms_window"}
|
||||
{"date": "2026-09-30", "unit": "EterLib/Input.cpp", "action": "port", "evidence": "host key events instead of DirectInput polling; IsPressed/Reset verbatim; port.input"}
|
||||
{"date": "2026-09-30", "unit": "EterImageLib/Image.cpp", "action": "port", "evidence": "verbatim; port.eter_image"}
|
||||
{"date": "2026-09-30", "unit": "EterImageLib/TGAImage.cpp", "action": "port", "evidence": "verbatim; raw save/load flips (desc 0x08), RLE load; port.eter_image"}
|
||||
{"date": "2026-09-30", "unit": "EterImageLib/DXTCImage.cpp", "action": "port", "evidence": "verbatim + DWORD_PTR casts + <d3d.h> ddraw shim; -fno-strict-aliasing for MSVC type punning; port.eter_image"}
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
{
|
||||
"reference": "EterImageLib/DXTCImage.cpp",
|
||||
"reference_sha256": "7e1c9d4a562441aea08b89892ab74907a582c6e0c2c8fd1ccce7fe7a300eead2",
|
||||
"priority": "P4",
|
||||
"contracts": [],
|
||||
"functions": {
|
||||
"CDXTCImage::CDXTCImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::CDXTCImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::~CDXTCImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::~CDXTCImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::Initialize": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::Initialize"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::Clear": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::Clear"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::LoadFromFile": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::LoadFromFile"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::LoadHeaderFromMemory": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::LoadHeaderFromMemory"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::LoadFromMemory": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::LoadFromMemory"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::Copy": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::Copy"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::Unextract": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::Unextract"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::Decompress": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::Decompress"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"GetColorBlockColors": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:GetColorBlockColors"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"DecodeColorBlock": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:DecodeColorBlock"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
],
|
||||
"note": "verbatim; reads Color8888 through DWORD* (MSVC aliasing) — port targets build with -fno-strict-aliasing"
|
||||
},
|
||||
"DecodeAlphaExplicit": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:DecodeAlphaExplicit"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"DecodeAlpha3BitLinear": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:DecodeAlpha3BitLinear"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::DecompressDXT1": {
|
||||
"status": "ADAPTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::DecompressDXT1"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
],
|
||||
"note": "40250: block/pixel addresses via (DWORD) pointer casts. Port: (DWORD_PTR). Invariant: the same byte offsets; a DWORD would truncate a 64-bit pointer."
|
||||
},
|
||||
"CDXTCImage::DecompressDXT3": {
|
||||
"status": "ADAPTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::DecompressDXT3"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
],
|
||||
"note": "40250: block/pixel addresses via (DWORD) pointer casts. Port: (DWORD_PTR). Invariant: the same byte offsets; a DWORD would truncate a 64-bit pointer."
|
||||
},
|
||||
"CDXTCImage::DecompressDXT5": {
|
||||
"status": "ADAPTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::DecompressDXT5"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
],
|
||||
"note": "40250: block/pixel addresses via (DWORD) pointer casts. Port: (DWORD_PTR). Invariant: the same byte offsets; a DWORD would truncate a 64-bit pointer."
|
||||
},
|
||||
"CDXTCImage::DecompressARGB": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::DecompressARGB"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"GetNumberOfBits": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:GetNumberOfBits"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CDXTCImage::DecodePixelFormat": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/DXTCImage.cpp:CDXTCImage::DecodePixelFormat"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"reference": "EterImageLib/Image.cpp",
|
||||
"reference_sha256": "4117eebaa0f98aa4d5b75da728c824d148155fb27084ca0b95ea479b113ef204",
|
||||
"priority": "P4",
|
||||
"contracts": [],
|
||||
"functions": {
|
||||
"CImage::CImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::CImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::SetFileName": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::SetFileName"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::GetFileNameString": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::GetFileNameString"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::PutImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::PutImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::GetBasePointer": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::GetBasePointer"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::GetLinePointer": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::GetLinePointer"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::GetWidth": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::GetWidth"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::GetHeight": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::GetHeight"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::Clear": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::Clear"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::Create": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::Create"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::Destroy": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::Destroy"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::Initialize": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::Initialize"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::IsEmpty": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::IsEmpty"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::FlipTopToBottom": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::FlipTopToBottom"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CImage::~CImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/Image.cpp:CImage::~CImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"reference": "EterImageLib/TGAImage.cpp",
|
||||
"reference_sha256": "e60338a6416259f5abe9ab8541ba0bbe0790295aadd09794f31c8ccaba3e0c44",
|
||||
"priority": "P4",
|
||||
"contracts": [],
|
||||
"functions": {
|
||||
"CTGAImage::CTGAImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::CTGAImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::~CTGAImage": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::~CTGAImage"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::Create": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::Create"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::LoadFromMemory": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::LoadFromMemory"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::LoadFromDiskFile": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::LoadFromDiskFile"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::GetRLEPixelCount": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::GetRLEPixelCount"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::GetRawPixelCount": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::GetRawPixelCount"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::SetCompressed": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::SetCompressed"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::SetAlphaChannel": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::SetAlphaChannel"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
},
|
||||
"CTGAImage::SaveToDiskFile": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::SaveToDiskFile"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
],
|
||||
"note": "verbatim; the RLE branch reads m_pdwEndPtr, which 40250 never sets (no caller saves compressed; TargaResource only loads)"
|
||||
},
|
||||
"CTGAImage::GetHeader": {
|
||||
"status": "PORTED",
|
||||
"impl": [
|
||||
"src/platform/EterImageLib/TGAImage.cpp:CTGAImage::GetHeader"
|
||||
],
|
||||
"test": [
|
||||
"tests/port/port_eter_image_test.cpp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,92 +1,144 @@
|
||||
// Platform skeleton for EterImageLib/Image.h (40250 EterImageLib/Image.cpp), generated by platform_stub.py.
|
||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
||||
// 40250 EterImageLib/Image.cpp, verbatim.
|
||||
#include "EterImageLib/StdAfx.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "EterImageLib/Image.h"
|
||||
|
||||
#include "../PlatformStub.h"
|
||||
CImage::CImage(CImage & image)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
int w = image.GetWidth();
|
||||
int h = image.GetHeight();
|
||||
|
||||
Create(w, h);
|
||||
|
||||
DWORD * pdwDest = GetBasePointer();
|
||||
DWORD * pdwSrc = image.GetBasePointer();
|
||||
|
||||
memcpy(pdwDest, pdwSrc, w * h * sizeof(DWORD));
|
||||
}
|
||||
|
||||
void CImage::SetFileName(const char* c_szFileName)
|
||||
{
|
||||
m_stFileName = c_szFileName;
|
||||
}
|
||||
|
||||
const std::string& CImage::GetFileNameString()
|
||||
{
|
||||
return m_stFileName;
|
||||
}
|
||||
|
||||
void CImage::PutImage(int x, int y, CImage* pImage)
|
||||
{
|
||||
assert(x >= 0 && x + pImage->GetWidth() <= GetWidth());
|
||||
assert(y >= 0 && y + pImage->GetHeight() <= GetHeight());
|
||||
|
||||
int len = pImage->GetWidth() * sizeof(DWORD);
|
||||
|
||||
for (int j = 0; j < pImage->GetHeight(); ++j)
|
||||
{
|
||||
DWORD * pdwDest = GetLinePointer(y + j) + x;
|
||||
memcpy(pdwDest, pImage->GetLinePointer(j), len);
|
||||
}
|
||||
}
|
||||
|
||||
DWORD* CImage::GetBasePointer()
|
||||
{
|
||||
assert(m_pdwColors != NULL);
|
||||
return m_pdwColors;
|
||||
}
|
||||
|
||||
DWORD* CImage::GetLinePointer(int line)
|
||||
{
|
||||
assert(m_pdwColors != NULL);
|
||||
return m_pdwColors + line * m_width;
|
||||
}
|
||||
|
||||
int CImage::GetWidth() const
|
||||
{
|
||||
assert(m_pdwColors != NULL);
|
||||
return m_width;
|
||||
}
|
||||
|
||||
int CImage::GetHeight() const
|
||||
{
|
||||
assert(m_pdwColors != NULL);
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void CImage::Clear(DWORD color)
|
||||
{
|
||||
assert(m_pdwColors != NULL);
|
||||
|
||||
for (int y = 0; y < m_height; ++y)
|
||||
{
|
||||
DWORD * colorLine = &m_pdwColors[y * m_width];
|
||||
|
||||
for (int x = 0; x < m_width; ++x)
|
||||
colorLine[x] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void CImage::Create(int width, int height)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_pdwColors = new DWORD[m_width*m_height];
|
||||
}
|
||||
|
||||
void CImage::Destroy()
|
||||
{
|
||||
if (m_pdwColors)
|
||||
{
|
||||
delete [] m_pdwColors;
|
||||
m_pdwColors = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CImage::Initialize()
|
||||
{
|
||||
m_pdwColors = NULL;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
bool CImage::IsEmpty() const
|
||||
{
|
||||
return (m_pdwColors == NULL) ? true : false;
|
||||
}
|
||||
|
||||
void CImage::FlipTopToBottom()
|
||||
{
|
||||
DWORD * swap = new DWORD[m_width * m_height];
|
||||
|
||||
int row;
|
||||
UINT width = GetWidth();
|
||||
UINT height = GetHeight();
|
||||
DWORD * end_row;
|
||||
DWORD * start_row;
|
||||
|
||||
for (row = 0; row < GetHeight() / 2; row++)
|
||||
{
|
||||
end_row = &(m_pdwColors[width * (height - row - 1)]);
|
||||
start_row = &(m_pdwColors[width * row]);
|
||||
|
||||
memcpy(swap, end_row, width * sizeof(DWORD));
|
||||
memcpy(end_row, start_row, width * sizeof(DWORD));
|
||||
memcpy(start_row, swap, width * sizeof(DWORD));
|
||||
}
|
||||
|
||||
delete [] swap;
|
||||
}
|
||||
|
||||
CImage::CImage()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
CImage::CImage(CImage &)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CImage::~CImage()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::Destroy() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::Create(int, int) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::Clear(DWORD) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::GetWidth() const -> int
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<int>();
|
||||
}
|
||||
|
||||
auto CImage::GetHeight() const -> int
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<int>();
|
||||
}
|
||||
|
||||
auto CImage::GetBasePointer() -> DWORD *
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD *>();
|
||||
}
|
||||
|
||||
auto CImage::GetLinePointer(int) -> DWORD *
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<DWORD *>();
|
||||
}
|
||||
|
||||
auto CImage::PutImage(int, int, CImage *) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::FlipTopToBottom() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::SetFileName(const char *) -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CImage::GetFileNameString() -> const std::string &
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<const std::string &>();
|
||||
}
|
||||
|
||||
auto CImage::IsEmpty() const -> bool
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
}
|
||||
|
||||
auto CImage::Initialize() -> void
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
@@ -1,72 +1,365 @@
|
||||
// Platform skeleton for EterImageLib/TGAImage.h (40250 EterImageLib/TGAImage.cpp), generated by platform_stub.py.
|
||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
||||
// 40250 EterImageLib/TGAImage.cpp, verbatim.
|
||||
#include "EterImageLib/StdAfx.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "EterBase/MappedFile.h"
|
||||
#include "EterImageLib/TGAImage.h"
|
||||
|
||||
#include "../PlatformStub.h"
|
||||
|
||||
CTGAImage::CTGAImage()
|
||||
CTGAImage::CTGAImage() : m_dwFlag(0)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
CTGAImage::CTGAImage(CImage &)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
CTGAImage::~CTGAImage()
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
}
|
||||
|
||||
auto CTGAImage::Create(int, int) -> void
|
||||
CTGAImage::CTGAImage(CImage &image) : m_dwFlag(0)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
int w = image.GetWidth();
|
||||
int h = image.GetHeight();
|
||||
|
||||
Create(w, h);
|
||||
|
||||
DWORD * pdwDest = GetBasePointer();
|
||||
memcpy(pdwDest, image.GetBasePointer(), w * h * sizeof(DWORD));
|
||||
FlipTopToBottom();
|
||||
}
|
||||
|
||||
auto CTGAImage::LoadFromMemory(int, const BYTE *) -> bool
|
||||
void CTGAImage::Create(int width, int height)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
memset(&m_Header, 0, sizeof(m_Header));
|
||||
|
||||
m_Header.imgType = 2;
|
||||
m_Header.width = (short) width;
|
||||
m_Header.height = (short) height;
|
||||
m_Header.colorBits = 32;
|
||||
m_Header.desc = 0x08; // alpha channel 있음
|
||||
|
||||
CImage::Create(width, height);
|
||||
}
|
||||
|
||||
auto CTGAImage::LoadFromDiskFile(const char *) -> bool
|
||||
bool CTGAImage::LoadFromMemory(int iSize, const BYTE * c_pbMem)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
memcpy(&m_Header, c_pbMem, 18);
|
||||
c_pbMem += 18;
|
||||
iSize -= 18;
|
||||
|
||||
CImage::Create(m_Header.width, m_Header.height);
|
||||
|
||||
UINT hxw = m_Header.width * m_Header.height;
|
||||
BYTE r, g, b, a;
|
||||
DWORD i;
|
||||
|
||||
DWORD * pdwDest = GetBasePointer();
|
||||
|
||||
switch (m_Header.imgType)
|
||||
{
|
||||
case 3: // 알파만 있는 것 (1bytes per pixel, 거의 안쓰임)
|
||||
{
|
||||
for (i = 0; i < hxw; ++i)
|
||||
{
|
||||
a = (char) *(c_pbMem++);
|
||||
pdwDest[i] = (a << 24) | (a << 16) | (a << 8) | a;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // 압축 안된 TGA
|
||||
{
|
||||
if (m_Header.colorBits == 16) // 16bit
|
||||
{
|
||||
for (i = 0; i < hxw; ++i)
|
||||
{
|
||||
WORD w;
|
||||
|
||||
memcpy(&w, c_pbMem, sizeof(WORD));
|
||||
c_pbMem += sizeof(WORD);
|
||||
iSize -= sizeof(WORD);
|
||||
|
||||
b = (BYTE) (w & 0x1F);
|
||||
g = (BYTE) ((w >> 5) & 0x1F);
|
||||
r = (BYTE) ((w >> 10) & 0x1F);
|
||||
|
||||
b <<= 3;
|
||||
g <<= 3;
|
||||
r <<= 3;
|
||||
a = 0xff;
|
||||
|
||||
pdwDest[i] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
else if (m_Header.colorBits == 24) // 24bit
|
||||
{
|
||||
for (i = 0; i < hxw; ++i)
|
||||
{
|
||||
r = (BYTE) *(c_pbMem++); --iSize;
|
||||
g = (BYTE) *(c_pbMem++); --iSize;
|
||||
b = (BYTE) *(c_pbMem++); --iSize;
|
||||
a = 0xff;
|
||||
|
||||
pdwDest[i] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
else if (m_Header.colorBits == 32) // 32bit
|
||||
{
|
||||
int size = GetWidth();
|
||||
size *= GetHeight() * 4;
|
||||
|
||||
memcpy(pdwDest, c_pbMem, size);
|
||||
c_pbMem += size;
|
||||
iSize -= size;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 10: // 압축 된 TGA (RLE)
|
||||
{
|
||||
BYTE rle;
|
||||
|
||||
if (m_Header.colorBits == 24)
|
||||
{
|
||||
i = 0;
|
||||
while (i < hxw)
|
||||
{
|
||||
rle = (BYTE) *(c_pbMem++); --iSize;
|
||||
|
||||
if (rle < 0x80) // 압축 안된 곳
|
||||
{
|
||||
rle++;
|
||||
|
||||
while (rle)
|
||||
{
|
||||
b = (BYTE) *(c_pbMem++); --iSize;
|
||||
g = (BYTE) *(c_pbMem++); --iSize;
|
||||
r = (BYTE) *(c_pbMem++); --iSize;
|
||||
a = 0xff;
|
||||
pdwDest[i++] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
|
||||
if (i > hxw)
|
||||
{
|
||||
assert(!"RLE overflow");
|
||||
printf("RLE overflow");
|
||||
return false;
|
||||
}
|
||||
--rle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 압축 된 곳
|
||||
rle -= 127;
|
||||
|
||||
b = (BYTE) *(c_pbMem++); --iSize;
|
||||
g = (BYTE) *(c_pbMem++); --iSize;
|
||||
r = (BYTE) *(c_pbMem++); --iSize;
|
||||
a = 0xff;
|
||||
|
||||
while (rle)
|
||||
{
|
||||
pdwDest[i++] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
|
||||
if (i > hxw)
|
||||
{
|
||||
assert(!"RLE overflow");
|
||||
printf("RLE overflow");
|
||||
return false;
|
||||
}
|
||||
--rle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_Header.colorBits == 32)
|
||||
{
|
||||
i = 0;
|
||||
while (i < hxw)
|
||||
{
|
||||
rle = (BYTE) *(c_pbMem++); --iSize;
|
||||
|
||||
if (rle < 0x80)
|
||||
{
|
||||
rle++;
|
||||
|
||||
while (rle)
|
||||
{
|
||||
b = (BYTE) *(c_pbMem++); --iSize;
|
||||
g = (BYTE) *(c_pbMem++); --iSize;
|
||||
r = (BYTE) *(c_pbMem++); --iSize;
|
||||
a = (BYTE) *(c_pbMem++); --iSize;
|
||||
pdwDest[i++] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
|
||||
if (i > hxw)
|
||||
{
|
||||
assert(!"RLE overflow");
|
||||
printf("RLE overflow");
|
||||
return false;
|
||||
}
|
||||
--rle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rle -= 127;
|
||||
|
||||
b = (BYTE) *(c_pbMem++); --iSize;
|
||||
g = (BYTE) *(c_pbMem++); --iSize;
|
||||
r = (BYTE) *(c_pbMem++); --iSize;
|
||||
a = (BYTE) *(c_pbMem++); --iSize;
|
||||
|
||||
while (rle)
|
||||
{
|
||||
pdwDest[i++] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
|
||||
if (i > hxw)
|
||||
{
|
||||
assert(!"RLE overflow");
|
||||
printf("RLE overflow");
|
||||
return false;
|
||||
}
|
||||
|
||||
--rle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(m_Header.desc & 0x20))
|
||||
{
|
||||
FlipTopToBottom();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto CTGAImage::SaveToDiskFile(const char *) -> bool
|
||||
bool CTGAImage::LoadFromDiskFile(const char * c_szFileName)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<bool>();
|
||||
CMappedFile file;
|
||||
|
||||
const BYTE * c_pbMap;
|
||||
|
||||
if (!file.Create(c_szFileName, (const void **) &c_pbMap, 0, 0))
|
||||
return false;
|
||||
|
||||
return LoadFromMemory(file.Size(), c_pbMap);
|
||||
}
|
||||
|
||||
auto CTGAImage::SetCompressed(bool) -> void
|
||||
int CTGAImage::GetRLEPixelCount(const DWORD * data)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
int r = 0;
|
||||
DWORD pixel;
|
||||
|
||||
r = 1;
|
||||
|
||||
if (data >= m_pdwEndPtr)
|
||||
return 0;
|
||||
|
||||
pixel = *data;
|
||||
|
||||
while ((r < 127) && (data < m_pdwEndPtr))
|
||||
{
|
||||
if (pixel != *(++data))
|
||||
return r;
|
||||
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
auto CTGAImage::SetAlphaChannel(bool) -> void
|
||||
int CTGAImage::GetRawPixelCount(const DWORD * data)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
int i = 0;
|
||||
|
||||
if (data >= m_pdwEndPtr)
|
||||
return 0;
|
||||
|
||||
while ((data < m_pdwEndPtr) && (i < 127))
|
||||
{
|
||||
int rle = GetRLEPixelCount(data);
|
||||
|
||||
if (rle >= 4)
|
||||
break;
|
||||
|
||||
data++;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
auto CTGAImage::GetHeader() -> TGA_HEADER &
|
||||
void CTGAImage::SetCompressed(bool isCompress)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<TGA_HEADER &>();
|
||||
if (isCompress)
|
||||
m_Header.imgType = 10;
|
||||
else
|
||||
m_Header.imgType = 2;
|
||||
}
|
||||
|
||||
auto CTGAImage::GetRawPixelCount(const DWORD *) -> int
|
||||
void CTGAImage::SetAlphaChannel(bool isExist)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<int>();
|
||||
if (isExist)
|
||||
m_Header.desc |= 0x08;
|
||||
else
|
||||
m_Header.desc &= ~0x08;
|
||||
}
|
||||
|
||||
auto CTGAImage::GetRLEPixelCount(const DWORD *) -> int
|
||||
bool CTGAImage::SaveToDiskFile(const char* c_szFileName)
|
||||
{
|
||||
MT_PLATFORM_STUB();
|
||||
return mt_platform_stub_return<int>();
|
||||
FILE * fp = fopen(c_szFileName, "wb");
|
||||
|
||||
if (!fp)
|
||||
return false;
|
||||
|
||||
fwrite(&m_Header, 18, 1, fp);
|
||||
|
||||
if (m_Header.imgType == 10) // RLE 압축으로 저장
|
||||
{
|
||||
DWORD * data = GetBasePointer();
|
||||
|
||||
while (data < m_pdwEndPtr)
|
||||
{
|
||||
int rle = GetRLEPixelCount(data);
|
||||
|
||||
if (rle < 4)
|
||||
{
|
||||
int raw = GetRawPixelCount(data);
|
||||
|
||||
if (raw == 0)
|
||||
break;
|
||||
|
||||
fputc(raw - 1, fp);
|
||||
|
||||
while (raw)
|
||||
{
|
||||
fwrite(data, sizeof(DWORD), 1, fp);
|
||||
data++;
|
||||
raw--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fputc((rle - 1) | 0x80, fp);
|
||||
fwrite(data, sizeof(DWORD), 1, fp);
|
||||
data += rle;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = GetWidth();
|
||||
size *= GetHeight() * 4;
|
||||
fwrite(GetBasePointer(), size, 1, fp);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
TGA_HEADER & CTGAImage::GetHeader()
|
||||
{
|
||||
return m_Header;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ endif()
|
||||
set(MT_PORT_WARNING_FLAGS)
|
||||
if(NOT MSVC)
|
||||
set(MT_PORT_WARNING_FLAGS -Wno-unknown-pragmas -Wno-format-security)
|
||||
# MSVC does no type-based alias analysis and 40250 relies on it (DXTCImage reads a Color8888 through a
|
||||
# DWORD*; clang -O2 then loads the colour before it is written).
|
||||
list(APPEND MT_PORT_WARNING_FLAGS -fno-strict-aliasing)
|
||||
endif()
|
||||
target_compile_options(port_logic PUBLIC ${MT_PORT_WARNING_FLAGS})
|
||||
# 40250 headers keep `#pragma comment(lib, "d3d8.lib")` etc. verbatim; clang turns them into ELF
|
||||
@@ -208,6 +211,9 @@ if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
|
||||
add_executable(port_input_test ${PROJECT_SOURCE_DIR}/tests/port/port_input_test.cpp)
|
||||
target_link_libraries(port_input_test PRIVATE port_platform)
|
||||
add_test(NAME port.input COMMAND $<TARGET_FILE:port_input_test>)
|
||||
add_executable(port_eter_image_test ${PROJECT_SOURCE_DIR}/tests/port/port_eter_image_test.cpp)
|
||||
target_link_libraries(port_eter_image_test PRIVATE port_platform)
|
||||
add_test(NAME port.eter_image COMMAND $<TARGET_FILE:port_eter_image_test>)
|
||||
|
||||
# MilesLib: the 40250 sound managers over the Miles emulation (platform/MilesLib/MilesAil.cpp).
|
||||
add_executable(port_miles_test ${PROJECT_SOURCE_DIR}/tests/port/port_miles_test.cpp)
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#pragma once
|
||||
// Shim for the DirectX 7 <d3d.h> on non-Windows targets: the <ddraw.h> surface description 40250
|
||||
// EterImageLib/DXTCImage.cpp copies straight out of a .dds file (the 124 bytes after the "DDS " magic).
|
||||
//
|
||||
// PORT: lpSurface is a pointer in <ddraw.h>, 4 bytes in the 32-bit client; it is a DWORD here so the
|
||||
// structure keeps the on-disk layout on 64-bit targets.
|
||||
#include "../win32/windows.h"
|
||||
|
||||
#define DDSD_CAPS 0x00000001l
|
||||
#define DDSD_HEIGHT 0x00000002l
|
||||
#define DDSD_WIDTH 0x00000004l
|
||||
#define DDSD_PITCH 0x00000008l
|
||||
#define DDSD_PIXELFORMAT 0x00001000l
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000l
|
||||
#define DDSD_LINEARSIZE 0x00080000l
|
||||
|
||||
#define DDPF_ALPHAPIXELS 0x00000001l
|
||||
#define DDPF_FOURCC 0x00000004l
|
||||
#define DDPF_RGB 0x00000040l
|
||||
#define DDPF_ALPHAPREMULT 0x00008000l
|
||||
|
||||
typedef struct _DDCOLORKEY
|
||||
{
|
||||
DWORD dwColorSpaceLowValue;
|
||||
DWORD dwColorSpaceHighValue;
|
||||
} DDCOLORKEY;
|
||||
|
||||
typedef struct _DDPIXELFORMAT
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwFourCC;
|
||||
union
|
||||
{
|
||||
DWORD dwRGBBitCount;
|
||||
DWORD dwYUVBitCount;
|
||||
DWORD dwZBufferBitDepth;
|
||||
DWORD dwAlphaBitDepth;
|
||||
DWORD dwLuminanceBitCount;
|
||||
DWORD dwBumpBitCount;
|
||||
DWORD dwPrivateFormatBitCount;
|
||||
};
|
||||
union
|
||||
{
|
||||
DWORD dwRBitMask;
|
||||
DWORD dwYBitMask;
|
||||
DWORD dwStencilBitDepth;
|
||||
DWORD dwLuminanceBitMask;
|
||||
DWORD dwBumpDuBitMask;
|
||||
DWORD dwOperations;
|
||||
};
|
||||
union
|
||||
{
|
||||
DWORD dwGBitMask;
|
||||
DWORD dwUBitMask;
|
||||
DWORD dwZBitMask;
|
||||
DWORD dwBumpDvBitMask;
|
||||
};
|
||||
union
|
||||
{
|
||||
DWORD dwBBitMask;
|
||||
DWORD dwVBitMask;
|
||||
DWORD dwStencilBitMask;
|
||||
DWORD dwBumpLuminanceBitMask;
|
||||
};
|
||||
union
|
||||
{
|
||||
DWORD dwRGBAlphaBitMask;
|
||||
DWORD dwYUVAlphaBitMask;
|
||||
DWORD dwLuminanceAlphaBitMask;
|
||||
DWORD dwRGBZBitMask;
|
||||
DWORD dwYUVZBitMask;
|
||||
};
|
||||
} DDPIXELFORMAT;
|
||||
|
||||
typedef struct _DDSCAPS2
|
||||
{
|
||||
DWORD dwCaps;
|
||||
DWORD dwCaps2;
|
||||
DWORD dwCaps3;
|
||||
DWORD dwCaps4;
|
||||
} DDSCAPS2;
|
||||
|
||||
typedef struct _DDSURFACEDESC2
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwHeight;
|
||||
DWORD dwWidth;
|
||||
union
|
||||
{
|
||||
LONG lPitch;
|
||||
DWORD dwLinearSize;
|
||||
};
|
||||
union
|
||||
{
|
||||
DWORD dwBackBufferCount;
|
||||
DWORD dwDepth;
|
||||
};
|
||||
union
|
||||
{
|
||||
DWORD dwMipMapCount;
|
||||
DWORD dwRefreshRate;
|
||||
DWORD dwSrcVBHandle;
|
||||
};
|
||||
DWORD dwAlphaBitDepth;
|
||||
DWORD dwReserved;
|
||||
DWORD lpSurface;
|
||||
union
|
||||
{
|
||||
DDCOLORKEY ddckCKDestOverlay;
|
||||
DWORD dwEmptyFaceColor;
|
||||
};
|
||||
DDCOLORKEY ddckCKDestBlt;
|
||||
DDCOLORKEY ddckCKSrcOverlay;
|
||||
DDCOLORKEY ddckCKSrcBlt;
|
||||
DDPIXELFORMAT ddpfPixelFormat;
|
||||
DDSCAPS2 ddsCaps;
|
||||
DWORD dwTextureStage;
|
||||
} DDSURFACEDESC2, *LPDDSURFACEDESC2;
|
||||
|
||||
static_assert(sizeof(DDPIXELFORMAT) == 32 && sizeof(DDSURFACEDESC2) == 124, "the .dds header layout");
|
||||
@@ -0,0 +1,125 @@
|
||||
// 40250 EterImageLib (CImage, CTGAImage, CDXTCImage), verbatim on the platform.
|
||||
#include "EterImageLib/StdAfx.h"
|
||||
#include "EterImageLib/TGAImage.h"
|
||||
#include "EterImageLib/DXTCImage.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
// "DDS " + a 124-byte DDSURFACEDESC2 (linear size, FourCC) + the blocks of one 4x4 level.
|
||||
std::vector<BYTE> MakeDDS(const char* fourcc, const std::vector<BYTE>& blocks)
|
||||
{
|
||||
std::vector<BYTE> dds(4 + 124, 0);
|
||||
memcpy(&dds[0], "DDS ", 4);
|
||||
DWORD* h = reinterpret_cast<DWORD*>(&dds[4]);
|
||||
h[0] = 124;
|
||||
h[1] = 0x1 | 0x2 | 0x4 | 0x1000 | 0x80000; // CAPS|HEIGHT|WIDTH|PIXELFORMAT|LINEARSIZE
|
||||
h[2] = 4;
|
||||
h[3] = 4;
|
||||
h[4] = DWORD(blocks.size());
|
||||
h[18] = 32; // ddpfPixelFormat.dwSize (offset 72)
|
||||
h[19] = 0x4; // DDPF_FOURCC
|
||||
memcpy(&h[20], fourcc, 4);
|
||||
dds.insert(dds.end(), blocks.begin(), blocks.end());
|
||||
return dds;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int failures = 0;
|
||||
auto check = [&failures](bool ok, const char *name) {
|
||||
if (!ok) {
|
||||
std::fprintf(stderr, "FAIL %s\n", name);
|
||||
++failures;
|
||||
}
|
||||
};
|
||||
|
||||
// CImage: Clear, PutImage clips nothing, FlipTopToBottom swaps rows.
|
||||
{
|
||||
CImage a, b;
|
||||
a.Create(4, 2);
|
||||
a.Clear(0x11111111);
|
||||
b.Create(2, 1);
|
||||
b.Clear(0x22222222);
|
||||
a.PutImage(1, 1, &b);
|
||||
check(a.GetLinePointer(1)[1] == 0x22222222 && a.GetLinePointer(1)[3] == 0x11111111 && a.GetLinePointer(0)[1] == 0x11111111, "PutImage");
|
||||
a.FlipTopToBottom();
|
||||
check(a.GetLinePointer(0)[2] == 0x22222222 && a.GetLinePointer(1)[2] == 0x11111111, "FlipTopToBottom");
|
||||
check(!a.IsEmpty() && a.GetWidth() == 4 && a.GetHeight() == 2, "CImage size");
|
||||
}
|
||||
|
||||
// CTGAImage: SaveToDiskFile writes the rows as stored with a bottom-left origin (desc 0x08), so loading
|
||||
// the file back flips it (the CTGAImage(CImage&) constructor pre-flips for that). RLE saving is not
|
||||
// exercised: 40250 never sets m_pdwEndPtr (no caller saves compressed; TargaResource only loads).
|
||||
{
|
||||
CTGAImage img;
|
||||
img.Create(5, 3);
|
||||
DWORD* p = img.GetBasePointer();
|
||||
for (int i = 0; i < 15; ++i)
|
||||
p[i] = 0x80000000u + DWORD(i);
|
||||
char path[] = "/tmp/mt_tga_XXXXXX";
|
||||
close(mkstemp(path));
|
||||
check(img.SaveToDiskFile(path), "TGA SaveToDiskFile");
|
||||
CTGAImage back;
|
||||
check(back.LoadFromDiskFile(path), "TGA LoadFromDiskFile");
|
||||
bool flipped = back.GetWidth() == 5 && back.GetHeight() == 3;
|
||||
for (int y = 0; flipped && y < 3; ++y)
|
||||
for (int x = 0; x < 5; ++x)
|
||||
flipped = flipped && back.GetLinePointer(y)[x] == p[(2 - y) * 5 + x];
|
||||
check(flipped, "TGA raw round trip is flipped");
|
||||
check(back.GetHeader().width == 5 && back.GetHeader().colorBits == 32, "TGA header");
|
||||
remove(path);
|
||||
}
|
||||
// RLE (type 10), 32-bit, top-left origin: a run packet then a raw packet, BGRA bytes.
|
||||
{
|
||||
std::vector<BYTE> tga(18, 0);
|
||||
tga[2] = 10;
|
||||
tga[12] = 5;
|
||||
tga[14] = 1;
|
||||
tga[16] = 32;
|
||||
tga[17] = 0x28;
|
||||
const BYTE body[] = {0x82, 1, 2, 3, 4, 0x01, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
tga.insert(tga.end(), body, body + sizeof(body));
|
||||
CTGAImage img;
|
||||
check(img.LoadFromMemory(int(tga.size()), tga.data()), "TGA RLE load");
|
||||
DWORD* p = img.GetBasePointer();
|
||||
check(p[0] == 0x04030201 && p[2] == 0x04030201 && p[3] == 0x08070605 && p[4] == 0x0C0B0A09, "TGA RLE pixels");
|
||||
}
|
||||
|
||||
// CDXTCImage DXT1: 565 endpoints shifted to 888 without replication, 4-colour mode thirds, rows LSB first.
|
||||
{
|
||||
std::vector<BYTE> block = {0x00, 0xF8, 0x1F, 0x00, 0xE4, 0x00, 0x00, 0x00};
|
||||
std::vector<BYTE> dds = MakeDDS("DXT1", block);
|
||||
CDXTCImage image;
|
||||
check(image.LoadFromMemory(dds.data()), "DXT1 LoadFromMemory");
|
||||
check(image.m_CompFormat == PF_DXT1 && image.m_nWidth == 4 && image.m_dwMipMapCount == 1, "DXT1 header");
|
||||
DWORD px[16] = {};
|
||||
image.Decompress(0, px);
|
||||
check(px[0] == 0xFFF80000 && px[1] == 0xFF0000F8 && px[2] == 0xFFA50052 && px[3] == 0xFF5200A5, "DXT1 row 0");
|
||||
check(px[4] == 0xFFF80000 && px[15] == 0xFFF80000, "DXT1 index 0 rows");
|
||||
}
|
||||
|
||||
// CDXTCImage DXT5: alpha0/alpha1 with 3-bit indices, then the colour block.
|
||||
{
|
||||
std::vector<BYTE> block = {0x80, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xF8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
std::vector<BYTE> dds = MakeDDS("DXT5", block);
|
||||
CDXTCImage image;
|
||||
check(image.LoadFromMemory(dds.data()) && image.m_CompFormat == PF_DXT5, "DXT5 load");
|
||||
DWORD px[16] = {};
|
||||
image.Decompress(0, px);
|
||||
check(px[0] == 0x10F80000 && px[1] == 0x80F80000 && px[15] == 0x80F80000, "DXT5 alpha");
|
||||
}
|
||||
|
||||
// A format other than DXT1/3/5 is refused.
|
||||
{
|
||||
std::vector<BYTE> dds = MakeDDS("ATI2", std::vector<BYTE>(16, 0));
|
||||
CDXTCImage image;
|
||||
check(!image.LoadFromMemory(dds.data()), "unknown FourCC refused");
|
||||
}
|
||||
return failures ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user