Skip to content

Commit

Permalink
Yoink THP from mkdd -- matches perfectly
Browse files Browse the repository at this point in the history
  • Loading branch information
Mrkol committed Feb 5, 2025
1 parent e7c9302 commit 67a4f11
Show file tree
Hide file tree
Showing 4 changed files with 2,553 additions and 3 deletions.
6 changes: 3 additions & 3 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,9 +740,9 @@ def MatchingFor(*versions):
Object(Matching, "dolphin/exi/EXIBios.c"),
Object(Matching, "dolphin/exi/EXIUart.c"),
]),
DolphinLib("thp", [
Object(NonMatching, "dolphin/thp/THPDec.c"),
Object(NonMatching, "dolphin/thp/THPAudio.c"),
DolphinLibUnpatched("thp", [
Object(Matching, "dolphin/thp/THPDec.c"),
Object(Matching, "dolphin/thp/THPAudio.c"),
]),
# TODO: is this actually part of the SDK?
{
Expand Down
113 changes: 113 additions & 0 deletions include/dolphin/thp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#ifndef _DOLPHIN_THP_H
#define _DOLPHIN_THP_H

#include <dolphin/types.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef u8 THPSample;
typedef s16 THPCoeff;
typedef float THPQuantTab[64];

typedef struct _THPHuffmanTab {
u8 quick[32];
u8 increment[32];
u8* Vij;
s32 maxCode[18];
s32 valPtr[18];
u8 Vij1;
u8 pad[11];
} THPHuffmanTab;

typedef struct _THPComponent {
u8 quantizationTableSelector;
u8 DCTableSelector;
u8 ACTableSelector;
THPCoeff predDC;
} THPComponent;

typedef struct _THPFileInfo {
THPQuantTab quantTabs[3];
THPHuffmanTab huffmanTabs[4];
THPComponent components[3];
u16 xPixelSize;
u16 yPixelSize;
u16 MCUsPerRow;
u16 decompressedY;
u8* c;
u32 currByte;
u32 cnt;
u8 validHuffmanTabs;
u8 RST;
u16 nMCU;
u16 currMCU;
u8* dLC[3];
} THPFileInfo;

typedef struct {
u32 offsetNextChannel;
u32 sampleSize;
s16 lCoef[8][2];
s16 rCoef[8][2];
s16 lYn1;
s16 lYn2;
s16 rYn1;
s16 rYn2;
} THPAudioRecordHeader;

typedef struct {
u8* encodeData;
u32 offsetNibbles;
u8 predictor;
u8 scale;
s16 yn1;
s16 yn2;
} THPAudioDecodeInfo;

BOOL THPInit();
s32 THPVideoDecode(void* file, void* tileY, void* tileU, void* tileV,
void* work);
u32 THPAudioDecode(s16* audioBuffer, u8* audioFrame, s32 flag);

static s32 __THPAudioGetNewSample(THPAudioDecodeInfo*);
static void __THPAudioInitialize(THPAudioDecodeInfo*, u8*);

static void __THPSetupBuffers(void);
static u8 __THPReadFrameHeader(void);
static u8 __THPReadScaneHeader(void);
static u8 __THPReadQuantizationTable(void);
static u8 __THPReadHuffmanTableSpecification(void);
static void __THPHuffGenerateSizeTable(void);
static void __THPHuffGenerateCodeTable(void);
static void __THPHuffGenerateDecoderTables(u8 tabIndex);
static void __THPRestartDefinition(void);
static void __THPPrepBitStream(void);
static void __THPDecompressYUV(void*, void*, void*);
static void __THPGQRRestore(void);
static void __THPDecompressiMCURow512x448(void);
static void __THPDecompressiMCURow640x480(void);
static void __THPDecompressiMCURowNxN(void);
static void __THPHuffDecodeDCTCompY(THPFileInfo*, THPCoeff*);
static void __THPHuffDecodeDCTCompU(THPFileInfo*, THPCoeff*);
static void __THPHuffDecodeDCTCompV(THPFileInfo*, THPCoeff*);

static const u8 __THPJpegNaturalOrder[80] = {
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
};

static const f64 __THPAANScaleFactor[8] = {
1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
1.0f, 0.785694958f, 0.541196100f, 0.275899379f,
};

#ifdef __cplusplus
}
#endif

#endif
171 changes: 171 additions & 0 deletions src/dolphin/thp/THPAudio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
#include <dolphin/thp.h>

u32 THPAudioDecode(s16* audioBuffer, u8* audioFrame, s32 flag)
{
THPAudioRecordHeader* header;
THPAudioDecodeInfo decInfo;
u8 *left, *right;
s16 *decLeftPtr, *decRightPtr;
s16 yn1, yn2;
s32 i;
s32 step;
s32 sample;
s64 yn;

if (audioBuffer == NULL || audioFrame == NULL) {
return 0;
}

header = (THPAudioRecordHeader*)audioFrame;
left = audioFrame + sizeof(THPAudioRecordHeader);
right = left + header->offsetNextChannel;

if (flag == 1) {
decRightPtr = audioBuffer;
decLeftPtr = audioBuffer + header->sampleSize;
step = 1;
} else {
decRightPtr = audioBuffer;
decLeftPtr = audioBuffer + 1;
step = 2;
}

if (header->offsetNextChannel == 0) {
__THPAudioInitialize(&decInfo, left);

yn1 = header->lYn1;
yn2 = header->lYn2;

for (i = 0; i < header->sampleSize; i++) {
sample = __THPAudioGetNewSample(&decInfo);
yn = header->lCoef[decInfo.predictor][1] * yn2;
yn += header->lCoef[decInfo.predictor][0] * yn1;
yn += (sample << decInfo.scale) << 11;
yn <<= 5;

if ((u16)(yn & 0xffff) > 0x8000) {
yn += 0x10000;
} else if ((u16)(yn & 0xffff) == 0x8000) {
if ((yn & 0x10000))
yn += 0x10000;
}

if (yn > 2147483647LL) {
yn = 2147483647LL;
}

if (yn < -2147483648LL) {
yn = -2147483648LL;
}

*decLeftPtr = (s16)(yn >> 16);
decLeftPtr += step;
*decRightPtr = (s16)(yn >> 16);
decRightPtr += step;
yn2 = yn1;
yn1 = (s16)(yn >> 16);
}
} else {
__THPAudioInitialize(&decInfo, left);

yn1 = header->lYn1;
yn2 = header->lYn2;

for (i = 0; i < header->sampleSize; i++) {
sample = __THPAudioGetNewSample(&decInfo);
yn = header->lCoef[decInfo.predictor][1] * yn2;
yn += header->lCoef[decInfo.predictor][0] * yn1;
yn += (sample << decInfo.scale) << 11;
yn <<= 5;
if ((u16)(yn & 0xffff) > 0x8000) {
yn += 0x10000;
} else {
if ((u16)(yn & 0xffff) == 0x8000) {
if ((yn & 0x10000))
yn += 0x10000;
}
}

if (yn > 2147483647LL) {
yn = 2147483647LL;
}

if (yn < -2147483648LL) {
yn = -2147483648LL;
}

*decLeftPtr = (s16)(yn >> 16);
decLeftPtr += step;
yn2 = yn1;
yn1 = (s16)(yn >> 16);
}

__THPAudioInitialize(&decInfo, right);

yn1 = header->rYn1;
yn2 = header->rYn2;

for (i = 0; i < header->sampleSize; i++) {
sample = __THPAudioGetNewSample(&decInfo);
yn = header->rCoef[decInfo.predictor][1] * yn2;
yn += header->rCoef[decInfo.predictor][0] * yn1;
yn += (sample << decInfo.scale) << 11;
yn <<= 5;

if ((u16)(yn & 0xffff) > 0x8000) {
yn += 0x10000;
} else {
if ((u16)(yn & 0xffff) == 0x8000) {
if ((yn & 0x10000))
yn += 0x10000;
}
}

if (yn > 2147483647LL) {
yn = 2147483647LL;
}

if (yn < -2147483648LL) {
yn = -2147483648LL;
}

*decRightPtr = (s16)(yn >> 16);
decRightPtr += step;
yn2 = yn1;
yn1 = (s16)(yn >> 16);
}
}

return header->sampleSize;
}

static s32 __THPAudioGetNewSample(THPAudioDecodeInfo* info)
{
s32 sample;

if (!(info->offsetNibbles & 0x0f)) {
info->predictor = (u8)((*(info->encodeData) & 0x70) >> 4);
info->scale = (u8)((*(info->encodeData) & 0xF));
info->encodeData++;
info->offsetNibbles += 2;
}

if (info->offsetNibbles & 0x1) {
sample = (s32)((*(info->encodeData) & 0xF) << 28) >> 28;
info->encodeData++;
} else {
sample = (s32)((*(info->encodeData) & 0xF0) << 24) >> 28;
}

info->offsetNibbles++;
return sample;
}

static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr)
{
info->encodeData = ptr;
info->offsetNibbles = 2;
info->predictor = (u8)((*(info->encodeData) & 0x70) >> 4);
info->scale = (u8)((*(info->encodeData) & 0xF));
info->encodeData++;
}
Loading

0 comments on commit 67a4f11

Please sign in to comment.