diff --git a/Makefile b/Makefile index 1ea59c0..60a0717 100644 --- a/Makefile +++ b/Makefile @@ -274,6 +274,8 @@ build/src/hal_libc.o: CFLAGS += -signed build/src/libleo/%.o: CC := $(CC_OLD) +build/src/jpegutils.o: CC := $(CC_OLD) + build/src/D470.o: CC := $(CC_OLD) build/src/D470.o: OPTFLAGS := -O0 build/src/D470.o: MIPS_VERSION := -mips1 diff --git a/linker_scripts/us/symbol_addrs_code.txt b/linker_scripts/us/symbol_addrs_code.txt index 6d813f8..0d07c3b 100644 --- a/linker_scripts/us/symbol_addrs_code.txt +++ b/linker_scripts/us/symbol_addrs_code.txt @@ -305,14 +305,14 @@ abs_asm = 0x8000B8A0; // type:func LeoBootGame = 0x8000B8B0; // type:func __LeoBootGame2 = 0x8000B9EC; // type:func __LeoBootGame3 = 0x8000BD10; // type:func -func_8000BD70 = 0x8000BD70; // type:func -func_8000BDD8 = 0x8000BDD8; // type:func -func_8000BE5C = 0x8000BE5C; // type:func -func_8000BEC8 = 0x8000BEC8; // type:func -func_8000BF70 = 0x8000BF70; // type:func +JpegUtils_ProcessQuantizationTable = 0x8000BD70; // type:func +JpegUtils_ParseHuffmanCodesLengths = 0x8000BDD8; // type:func +JpegUtils_GetHuffmanCodes = 0x8000BE5C; // type:func +JpegUtils_SetHuffmanTable = 0x8000BEC8; // type:func +JpegUtils_ProcessHuffmanTableImpl = 0x8000BF70; // type:func func_8000C02C = 0x8000C02C; // type:func -func_8000C104 = 0x8000C104; // type:func -func_8000C1AC = 0x8000C1AC; // type:func +JpegUtils_SetHuffmanTableOld = 0x8000C104; // type:func +JpegUtils_ProcessHuffmanTableImplOld = 0x8000C1AC; // type:func func_8000C280 = 0x8000C280; // type:func func_8000C4A8 = 0x8000C4A8; // type:func func_8000C644 = 0x8000C644; // type:func diff --git a/src/3FB0.c b/src/3FB0.c index 80b1041..10b6f88 100644 --- a/src/3FB0.c +++ b/src/3FB0.c @@ -119,7 +119,7 @@ void func_80003558(UnkStruct80001380* arg0, unk_func_80003680_sp90* arg1) { osCreateMesgQueue(&arg0->queue, &arg0->mesg, 1); } -void func_80003608(unk_func_80003680_sp27* arg0, unk_func_80003680_spB0* arg1, unk_func_80003680_sp300* arg2) { +void func_80003608(unk_func_80003680_sp27* arg0, JpegHuffmanTable* arg1, unk_func_80003680_sp300* arg2) { arg0->unk_00 = arg2->start_of_scan; arg0->unk_04 = arg2->unk_00; arg0->unk_05 = 2; @@ -143,7 +143,7 @@ s32 func_80003680(u32 addr, s32 arg1, u8* arg2) { UnkStruct80001380 sp318; unk_func_80003680_sp300 sp300; u8 sp200[2][0x80]; - unk_func_80003680_spB0 spB0[4]; + JpegHuffmanTable spB0[4]; u16* temp_s0; u8* temp_s3; unk_func_80003680_sp90 sp90; @@ -159,8 +159,8 @@ s32 func_80003680(u32 addr, s32 arg1, u8* arg2) { temp_s0 = Util_Malloc(0x210); func_800033C8(&sp300, arg2); - func_8000BD70(sp300.quantization_table, sp200, 2); - func_8000C02C(sp300.huffman_table, spB0, temp_s3, temp_s0, 4); + JpegUtils_ProcessQuantizationTable(sp300.quantization_table, sp200, 2); + JpegUtils_ProcessHuffmanTable(sp300.huffman_table, spB0, temp_s3, temp_s0, 4); Util_Free(temp_s0); Util_Free(temp_s3); diff --git a/src/3FB0.h b/src/3FB0.h index 9a73fd4..a31a0a0 100644 --- a/src/3FB0.h +++ b/src/3FB0.h @@ -3,7 +3,7 @@ #include "global.h" #include "5580.h" -#include "C970.h" +#include "jpegutils.h" #include "CE80.h" #include "src/memmap.h" #include "src/memory.h" @@ -87,7 +87,7 @@ typedef void (*ret_func_80004454)(void); s32 func_800033B0(u8* arg0); void func_800033C8(unk_func_80003680_sp300* arg0, u8* arg1); void func_80003558(UnkStruct80001380* arg0, unk_func_80003680_sp90* arg1); -void func_80003608(unk_func_80003680_sp27* arg0, unk_func_80003680_spB0* arg1, unk_func_80003680_sp300* arg2); +void func_80003608(unk_func_80003680_sp27* arg0, JpegHuffmanTable* arg1, unk_func_80003680_sp300* arg2); void func_80003648(unk_func_80003680_sp90* arg0, u8(arg1)[2][0x80], unk_func_80003680_sp300* arg2); s32 func_80003680(u32 addr, s32 arg1, u8* arg2); void func_80003860(void); diff --git a/src/C970.c b/src/C970.c deleted file mode 100644 index 9284a98..0000000 --- a/src/C970.c +++ /dev/null @@ -1,229 +0,0 @@ -#include "C970.h" - -typedef struct unk_func_8000C104_arg1 { - /* 0x000 */ u8 value; - /* 0x001 */ u8 pad01[0x0F]; - /* 0x010 */ u16 unk_10; - /* 0x012 */ u8 pad12[0xEE]; - /* 0x100 */ u16 unk_100; -} unk_func_8000C104_arg1; // size >= 0x102 - -#ifdef NON_MATCHING -void func_8000BD70(u8* in_quantization_tables, u8* out_quantization_tables, s32 num_tables) { - u8* src; - u8* dst; - s32 i; - s32 j; - s32 count; - - src = in_quantization_tables; - count = num_tables & 0xFF; - - for (i = 0; i < count; i++) { - src++; - - for (j = 0; j < 0x40; j++) { - dst = out_quantization_tables + (i << 7) + (j * 2); - *(s16*)dst = (s16)*src; - src++; - } - } -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000BD70.s") -#endif - -#ifdef NON_MATCHING -s16 func_8000BDD8(u8* arg0, u16* arg1) { - s16 var_a2; - s16 var_v1; - s8 i; - s8 var_v0; - u8* temp_a1; - - var_v0 = 1; - var_v1 = 0; - var_a2 = 1; - for (i = 1; i < 0x11; i = (var_v0 + 1) & 0xFF) { - temp_a1 = &arg0[i]; - if ((s32) temp_a1[-1] > 0) { - do { - arg1[var_v1] = var_v0; - var_a2 += 1; - var_v1 += 1; - } while ((s32) temp_a1[-1] >= var_a2); - var_a2 = 1; - } - var_v0 = i; - } - arg1[var_v1] = 0; - return var_v1; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000BDD8.s") -#endif - -#ifdef NON_MATCHING -s16 func_8000BE5C(u8* arg0, u16* arg1) { - s16 var_v0; - s16 var_v1; - s32 temp_t6; - u8 temp_t0; - u8 var_a2; - u8 var_a3; - - var_a2 = *arg0; - var_v1 = 0; - var_v0 = 0; - var_a3 = var_a2; - - while(1) { - temp_t6 = var_v1 * 2; - var_v1 += 1; - arg1[temp_t6] = var_v0; - temp_t0 = arg0[var_v1]; - var_v0 = (var_v0 + 1) & 0xFFFF; - if (var_a3 == temp_t0) { - continue; - } - if (temp_t0 != 0) { - do { - var_a3 = (var_a2 + 1) & 0xFF; - var_v0 = (var_v0 * 2) & 0xFFFF; - var_a2 = var_a3; - } while (temp_t0 != var_a3); - continue; - } - break; - } - return var_v1; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000BE5C.s") -#endif - -#ifdef NON_MATCHING -s8 func_8000BEC8(u8* arg0, unk_func_80003680_spB0* arg1, u16* arg2) { - s32 i; - s32 temp_t4; - s8 var_v1; - - var_v1 = 0; - for (i = 0; i < 16; i = (i + 1) & 0xFF) { - if (arg0[i] != 0) { - arg1->unk_00[i] = var_v1; - arg1->unk_10[i] = arg2[var_v1]; - temp_t4 = ((var_v1 + arg0[i]) - 1) & 0xFFFF; - var_v1 = (temp_t4 + 1); - arg1->unk_30[i] = arg2[temp_t4]; - } else { - arg1->unk_30[i] = 0xFFFF; - } - } - return var_v1; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000BEC8.s") -#endif - -#ifdef NON_MATCHING -s16 func_8000BF70(u8* arg0, unk_func_80003680_spB0* arg1, u8* arg2, u16* arg3, u8 arg4) { - s16 temp_v0; - - temp_v0 = func_8000BDD8(arg2, arg3); - if ((temp_v0 == 0) || ((arg4 != 0) && (temp_v0 >= 0x101)) || ((arg4 == 0) && (temp_v0 >= 0x11))) { - return 0; - } - if (func_8000BE5C(arg2, arg3) != temp_v0) { - return 0; - } - if (temp_v0 != func_8000BEC8(arg0, arg1, arg3)) { - return 0; - } - return temp_v0; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000BF70.s") -#endif - -#ifdef NON_MATCHING -s32 func_8000C02C(u8* arg0, unk_func_80003680_spB0* arg1, u8* arg2, u16* arg3, s32 arg4) { - s32 temp_at; - s32 temp_lo; - s32 temp_t8; - s32 temp_v0; - s32 var_s1; - u8* var_s0; - u8* temp_s0; - u8* temp_s0_2; - - var_s0 = arg0; - var_s1 = 0; - if ((s32) arg4 > 0) { - while(1) { - temp_lo = var_s1 * 0x54; - temp_s0 = var_s0 + 1; - temp_v0 = func_8000BF70(temp_s0, &arg1[temp_lo], arg2, arg3, (s32) *var_s0 >> 4); - temp_s0_2 = temp_s0 + 0x10; - if (temp_v0 == 0) { - return 1; - } - temp_t8 = (var_s1 + 1) & 0xFF; - temp_at = temp_t8 < (s32) arg4; - arg1[temp_lo].unk_50 = temp_s0_2; - var_s1 = temp_t8; - var_s0 = temp_s0_2 + temp_v0; - if (temp_at == 0) { - return 0; - } - } - } - return 0; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000C02C.s") -#endif - -#ifdef NON_MATCHING -void func_8000C104(u8* arg0, unk_func_8000C104_arg1* arg1, u8* arg2, u16* arg3, s16 arg4, u8 arg5) { - s16 i; - u8 temp_v1; - - for (i = 0; i < arg4; i++) { - temp_v1 = arg0[i]; - if (arg5 != 0) { - arg1[temp_v1 * 2].unk_100 = arg3[i]; - arg1[temp_v1].value = arg2[i]; - } else { - arg1[temp_v1 * 2].unk_10 = arg3[i]; - arg1[temp_v1].value = arg2[i]; - } - } -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000C104.s") -#endif - -#ifdef NON_MATCHING -s32 func_8000C1AC(u8* arg0, unk_func_8000C104_arg1* arg1, u8* arg2, u16* arg3) { - u8 sp2F; - s16 sp2C; - s16 temp_v0; - u8* temp_s0; - - temp_s0 = arg0 + 1; - sp2F = (u8) ((s32) *arg0 >> 4); - temp_v0 = func_8000BDD8(temp_s0, arg2); - if ((temp_v0 == 0) || ((sp2F != 0) && (temp_v0 >= 0x101)) || ((sp2F == 0) && (temp_v0 >= 0x11))) { - return 1; - } - sp2C = temp_v0; - if (func_8000BE5C(arg2, arg3) != temp_v0) { - return 1; - } - func_8000C104((u8*)temp_s0 + 0x10, arg1, arg2, arg3, temp_v0, sp2F); - return 0; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/C970/func_8000C1AC.s") -#endif diff --git a/src/C970.h b/src/C970.h deleted file mode 100644 index 24bfc0f..0000000 --- a/src/C970.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _C970_H_ -#define _C970_H_ - -#include "global.h" - -typedef struct unk_func_80003680_spB0 { - /* 0x00 */ u8 unk_00[16]; - /* 0x10 */ u16 unk_10[16]; - /* 0x30 */ u16 unk_30[16]; - /* 0x50 */ s32 unk_50; -} unk_func_80003680_spB0; // size = 0x54 - -void func_8000BD70(u8* in_quantization_tables, u8* out_quantization_tables, s32 num_tables); -s32 func_8000C02C(u8*, unk_func_80003680_spB0*, u8*, u16*, s32); - -#endif // _C970_H_ diff --git a/src/CE80.c b/src/CE80.c index dd7e639..9d4a1be 100644 --- a/src/CE80.c +++ b/src/CE80.c @@ -14,10 +14,10 @@ s32 func_8000C280(unk_func_80003680_sp27* arg0, u32 arg1, u32 arg2, u8 arg3, unk s16 sp60; u32 i; s32 sp58; - unk_func_80003680_spB0* temp_fp; - unk_func_80003680_spB0* temp_s4; - unk_func_80003680_spB0* temp_s5; - unk_func_80003680_spB0* temp_s7; + JpegHuffmanTable* temp_fp; + JpegHuffmanTable* temp_s4; + JpegHuffmanTable* temp_s5; + JpegHuffmanTable* temp_s7; sp58 = 0; D_800A82D0 = arg0->unk_00; @@ -93,7 +93,7 @@ s32 func_8000C280(unk_func_80003680_sp27* arg0, u32 arg1, u32 arg2, u8 arg3, unk #endif #ifdef NON_MATCHING -s32 func_8000C4A8(unk_func_80003680_spB0* arg0, unk_func_80003680_spB0* arg1, s16* arg2, s16* arg3) { +s32 func_8000C4A8(JpegHuffmanTable* arg0, JpegHuffmanTable* arg1, s16* arg2, s16* arg3) { s8 i; s8 sp36; s16 sp34; @@ -146,7 +146,7 @@ typedef struct sp24_func_8000C644 { } sp24_func_8000C644; #ifdef NON_MATCHING -s32 func_8000C644(unk_func_80003680_spB0* arg0, s16* arg1, s8* arg2) { +s32 func_8000C644(JpegHuffmanTable* arg0, s16* arg1, s8* arg2) { u8 i; sp24_func_8000C644 sp24; s16 temp_v0; @@ -157,7 +157,7 @@ s32 func_8000C644(unk_func_80003680_spB0* arg0, s16* arg1, s8* arg2) { for (i = 0; i < 16; i++) { sp24.unk_00 = temp_v0 >> (0xF - i); - if ((arg0->unk_30[i] != 0xFFFF) && !(arg0->unk_30[i] < sp24.unk_00)) { + if ((arg0->codesB[i] != 0xFFFF) && !(arg0->codesB[i] < sp24.unk_00)) { break; } } @@ -166,7 +166,7 @@ s32 func_8000C644(unk_func_80003680_spB0* arg0, s16* arg1, s8* arg2) { return 1; } - sp24.unk_02 = *(u8*)(((arg0->unk_00[i] + sp24.unk_00) - arg0->unk_10[i]) + arg0->unk_50); + sp24.unk_02 = *(u8*)(((arg0->codeOffs[i] + sp24.unk_00) - arg0->codesA[i]) + arg0->symbols); *arg2 = sp24.unk_02 >> 4; D_800A82D8 = (D_800A82D8 + i) - 0xF; diff --git a/src/CE80.h b/src/CE80.h index 478a2a2..db01d13 100644 --- a/src/CE80.h +++ b/src/CE80.h @@ -2,16 +2,16 @@ #define _CE80_H_ #include "global.h" -#include "C970.h" +#include "jpegutils.h" typedef struct unk_func_80003680_sp27 { /* 0x00 */ s32 unk_00; /* 0x04 */ u8 unk_04; /* 0x05 */ u8 unk_05; - /* 0x08 */ unk_func_80003680_spB0* unk_08; - /* 0x0C */ unk_func_80003680_spB0* unk_0C; - /* 0x10 */ unk_func_80003680_spB0* unk_10; - /* 0x14 */ unk_func_80003680_spB0* unk_14; + /* 0x08 */ JpegHuffmanTable* unk_08; + /* 0x0C */ JpegHuffmanTable* unk_0C; + /* 0x10 */ JpegHuffmanTable* unk_10; + /* 0x14 */ JpegHuffmanTable* unk_14; /* 0x18 */ s8 unk_18; } unk_func_80003680_sp27; // size == 0x1C @@ -26,8 +26,8 @@ typedef struct unk_func_80003680_sp60 { } unk_func_80003680_sp60; // size = 0x14 s32 func_8000C280(unk_func_80003680_sp27*, u32, u32, u8, unk_func_80003680_sp60*); -s32 func_8000C4A8(unk_func_80003680_spB0*, unk_func_80003680_spB0*, s16*, s16*); -s32 func_8000C644(unk_func_80003680_spB0*, s16*, s8*); +s32 func_8000C4A8(JpegHuffmanTable*, JpegHuffmanTable*, s16*, s16*); +s32 func_8000C644(JpegHuffmanTable*, s16*, s8*); u16 func_8000C780(u8); #endif // _CE80_H_ diff --git a/src/jpegutils.c b/src/jpegutils.c new file mode 100644 index 0000000..b0f41de --- /dev/null +++ b/src/jpegutils.c @@ -0,0 +1,159 @@ +#include "jpegutils.h" + +typedef struct JpegHuffmanTableOld { + /* 0x000 */ u8 codeOffs[16]; + /* 0x010 */ u16 dcCodes[120]; + /* 0x100 */ u16 acCodes[256]; +} JpegHuffmanTableOld; // size >= 0x300 + +void JpegUtils_ProcessQuantizationTable(u8* dqt, JpegQuantizationTable* qt, u8 num_tables) { + u8 i; + + for (i = 0; i < num_tables; i++) { + u8 j; + + dqt++; + for (j = 0; j < 64; j++) { + qt[i].table[j] = *dqt++; + } + } +} + +s32 JpegUtils_ParseHuffmanCodesLengths(u8* ptr, u8* codesLengths) { + u8 off = 1; + s16 count = 0; + s16 idx = 1; + + while (off < 0x11) { + while (idx <= ptr[off - 1]) { + codesLengths[count++] = off; + idx++; + } + idx = 1; + off++; + } + + codesLengths[count] = 0; + return count; +} + +s16 JpegUtils_GetHuffmanCodes(u8* codesLengths, u16* codes) { + s16 idx = 0; + u16 code = 0; + u8 lastLen = codesLengths[0]; + + while (true) { + while (true) { + codes[idx++] = code++; + + if (codesLengths[idx] != lastLen) { + break; + } + } + + if (codesLengths[idx] == 0) { + break; + } + + while (true) { + if (code <<= 1, codesLengths[idx] == ++lastLen) { + break; + } + } + } + + return idx; +} + +u16 JpegUtils_SetHuffmanTable(u8* data, JpegHuffmanTable* ht, u16* codes) { + u8 idx; + u16 codeOff = 0; + + for (idx = 0; idx < 0x10; idx++) { + if (data[idx]) { + ht->codeOffs[idx] = codeOff; + ht->codesA[idx] = codes[codeOff]; + codeOff += data[idx] - 1; + ht->codesB[idx] = codes[codeOff]; + codeOff++; + } else { + ht->codesB[idx] = 0xFFFF; + } + } + + return codeOff; +} + +u32 JpegUtils_ProcessHuffmanTableImpl(u8* data, JpegHuffmanTable* ht, u8* codesLengths, u16* codes, u8 isAc) { + s16 ret; + s32 count = JpegUtils_ParseHuffmanCodesLengths(data, codesLengths); + s32 temp; + + ret = count; + if (count == 0 || (isAc && count > 0x100) || (!isAc && count > 0x10)) { + return 0; + } + if (ret != JpegUtils_GetHuffmanCodes(codesLengths, codes)) { + return 0; + } + if (temp = JpegUtils_SetHuffmanTable(data, ht, codes), temp != ret) { + return 0; + } + + return ret; +} + +s32 JpegUtils_ProcessHuffmanTable(u8* dht, JpegHuffmanTable* ht, u8* codesLengths, u16* codes, u8 count) { + u8 idx; + u32 codeCount; + + for (idx = 0; idx < count; idx++) { + u32 ac = (*dht++ >> 4); + + codeCount = JpegUtils_ProcessHuffmanTableImpl(dht, &ht[idx], codesLengths, codes, ac); + if (codeCount == 0) { + return 1; + } + + dht += 0x10; + ht[idx].symbols = dht; + dht += codeCount; + } + return 0; +} + +void JpegUtils_SetHuffmanTableOld(u8* data, JpegHuffmanTableOld* ht, u8* codesLengths, u16* codes, s16 count, u8 isAc) { + s16 idx; + u8 a; + + for (idx = 0; idx < count; idx++) { + a = data[idx]; + if (isAc) { + ht->acCodes[a] = codes[idx]; + ht->codeOffs[a] = codesLengths[idx]; + } else { + ht->dcCodes[a] = codes[idx]; + ht->codeOffs[a] = codesLengths[idx]; + } + } +} + +u32 JpegUtils_ProcessHuffmanTableImplOld(u8* dht, JpegHuffmanTableOld* ht, u8* codesLengths, u16* codes) { + u8 isAc = *dht++ >> 4; + s16 count2; + s32 count; + + count2 = count = JpegUtils_ParseHuffmanCodesLengths(dht, codesLengths); + + if (count == 0 || (isAc && count > 0x100) || (!isAc && count > 0x10)) { + return 1; + } + + if (JpegUtils_GetHuffmanCodes(codesLengths, codes) != count2) { + return 1; + } + + JpegUtils_SetHuffmanTableOld(dht + 0x10, ht, codesLengths, codes, count2, isAc); + + return 0; +} \ No newline at end of file diff --git a/src/jpegutils.h b/src/jpegutils.h new file mode 100644 index 0000000..e70efb5 --- /dev/null +++ b/src/jpegutils.h @@ -0,0 +1,21 @@ +#ifndef JPEGUTILS_H +#define JPEGUTILS_H + +#include "global.h" + +typedef struct JpegHuffmanTable { + /* 0x00 */ u8 codeOffs[16]; + /* 0x10 */ u16 codesA[16]; + /* 0x30 */ u16 codesB[16]; + /* 0x50 */ u8* symbols; +} JpegHuffmanTable; // size = 0x54 + +typedef struct JpegQuantizationTable { + /* 0x00 */ u16 table[8*8]; +} JpegQuantizationTable; // size = 0x80 + +void JpegUtils_ProcessQuantizationTable(u8* dqt, JpegQuantizationTable* qt, u8 num_tables); +s32 JpegUtils_ProcessHuffmanTable(u8*, JpegHuffmanTable*, u8*, u16*, u8); +u16 JpegUtils_SetHuffmanTable(u8* data, JpegHuffmanTable* ht, u16* codes); + +#endif // JPEGUTILS_H diff --git a/yamls/us/rom.yaml b/yamls/us/rom.yaml index b107e9b..fbf0b71 100644 --- a/yamls/us/rom.yaml +++ b/yamls/us/rom.yaml @@ -47,7 +47,7 @@ - [0xC4A0, hasm, abs] # abs function - [0xC4B0, c, libleo/bootdisk] - [0xC910, hasm, ../../src/libleo/bootstrap] - - [0xC970, c] + - [0xC970, c, jpegutils] - [0xCE80, c] # - [0xD470, c] # - [0xDDC0, c]