diff --git a/linker_scripts/us/symbol_addrs.txt b/linker_scripts/us/symbol_addrs.txt index 004a065..9230f7e 100644 --- a/linker_scripts/us/symbol_addrs.txt +++ b/linker_scripts/us/symbol_addrs.txt @@ -564,6 +564,11 @@ D_30CD490 = 0x30CD490; D_30CD510 = 0x30CD510; D_8250A288 = 0x8250A288; // size:0xA D_800A62E0 = 0x800A62E0; // defined:true size:0xA40 +sJpegBitStreamPtr = 0x800A82D0; // defined:true size:0x4 +sJpegBitStreamByteIdx = 0x800A82D4; // defined:true size:0x4 +sJpegBitStreamBitIdx = 0x800A82D8; // defined:true size:0x1 +sJpegBitStreamDontSkip = 0x800A82D9; // defined:true size:0x1 +sJpegBitStreamCurWord = 0x800A82DC; // defined:true size:0x4 D_800A8320 = 0x800A8320; // size:0x74 D_800AA688 = 0x800AA688; D_80072B00 = 0x80072B00; // size:0x3DE diff --git a/linker_scripts/us/symbol_addrs_code.txt b/linker_scripts/us/symbol_addrs_code.txt index 0d07c3b..2838f84 100644 --- a/linker_scripts/us/symbol_addrs_code.txt +++ b/linker_scripts/us/symbol_addrs_code.txt @@ -310,13 +310,13 @@ 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 +JpegUtils_ProcessHuffmanTable = 0x8000C02C; // 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 -func_8000C780 = 0x8000C780; // type:func +JpegDecoder_Decode = 0x8000C280; // type:func +JpegDecoder_ProcessMcu = 0x8000C4A8; // type:func +JpegDecoder_ParseNextSymbol = 0x8000C644; // type:func +JpegDecoder_ReadBits = 0x8000C780; // type:func func_8000C870 = 0x8000C870; // type:func func_8000C8F8 = 0x8000C8F8; // type:func func_8000CA4C = 0x8000CA4C; // type:func diff --git a/src/3FB0.c b/src/3FB0.c index 10b6f88..ec0e76c 100644 --- a/src/3FB0.c +++ b/src/3FB0.c @@ -119,15 +119,15 @@ void func_80003558(UnkStruct80001380* arg0, unk_func_80003680_sp90* arg1) { osCreateMesgQueue(&arg0->queue, &arg0->mesg, 1); } -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; - arg0->unk_08 = &arg1[0]; - arg0->unk_0C = &arg1[2]; - arg0->unk_10 = &arg1[1]; - arg0->unk_14 = &arg1[3]; - arg0->unk_18 = arg2->unk_01; +void func_80003608(JpegDecoder* decoder, JpegHuffmanTable* hTable, unk_func_80003680_sp300* arg2) { + decoder->imageData = arg2->start_of_scan; + decoder->mode = arg2->unk_00; + decoder->unk_05 = 2; + decoder->hTablePtrs[0] = &hTable[0]; + decoder->hTablePtrs[1] = &hTable[2]; + decoder->hTablePtrs[2] = &hTable[1]; + decoder->hTablePtrs[3] = &hTable[3]; + decoder->unk_18 = arg2->unk_01; } void func_80003648(unk_func_80003680_sp90* arg0, u8(arg1)[2][0x80], unk_func_80003680_sp300* arg2) { @@ -147,8 +147,8 @@ s32 func_80003680(u32 addr, s32 arg1, u8* arg2) { u16* temp_s0; u8* temp_s3; unk_func_80003680_sp90 sp90; - unk_func_80003680_sp27 sp74; - unk_func_80003680_sp60 sp60; + JpegDecoder sp74; + JpegDecoderState sp60; u32 var_s1; s32 i; s32 j; @@ -177,7 +177,7 @@ s32 func_80003680(u32 addr, s32 arg1, u8* arg2) { return 0; } - if (func_8000C280(&sp74, addr, 1, var_s4, &sp60) != 0) { + if (JpegDecoder_Decode(&sp74, addr, 1, var_s4, &sp60) != 0) { return 0; } diff --git a/src/3FB0.h b/src/3FB0.h index a31a0a0..8316618 100644 --- a/src/3FB0.h +++ b/src/3FB0.h @@ -4,7 +4,7 @@ #include "global.h" #include "5580.h" #include "jpegutils.h" -#include "CE80.h" +#include "jpeg_decoder.h" #include "src/memmap.h" #include "src/memory.h" @@ -62,7 +62,7 @@ typedef struct unk_func_800041C0 { } unk_func_800041C0; // size >= 0x8 typedef struct unk_func_80003680_sp300 { - /* 0x00 */ u8 unk_00; + /* 0x00 */ u8 unk_00; // mode /* 0x01 */ u8 unk_01; /* 0x02 */ char unk02[0x2]; /* 0x04 */ s16 width; @@ -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, JpegHuffmanTable* arg1, unk_func_80003680_sp300* arg2); +void func_80003608(JpegDecoder* 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/CE80.c b/src/CE80.c deleted file mode 100644 index 9d4a1be..0000000 --- a/src/CE80.c +++ /dev/null @@ -1,226 +0,0 @@ -#include "CE80.h" - -extern u8* D_800A82D0; -extern s32 D_800A82D4; -extern u8 D_800A82D8; -extern u8 D_800A82D9; -extern u32 D_800A82DC; - -#ifdef NON_MATCHING -s32 func_8000C280(unk_func_80003680_sp27* arg0, u32 arg1, u32 arg2, u8 arg3, unk_func_80003680_sp60* arg4) { - u16 var_v0; - s16 sp64; - s16 sp62; - s16 sp60; - u32 i; - s32 sp58; - JpegHuffmanTable* temp_fp; - JpegHuffmanTable* temp_s4; - JpegHuffmanTable* temp_s5; - JpegHuffmanTable* temp_s7; - - sp58 = 0; - D_800A82D0 = arg0->unk_00; - - if (arg0->unk_04 == 0) { - var_v0 = 2; - } else { - var_v0 = 4; - if (arg0->unk_05 == 1) { - sp58 = 0x80; - } - } - - temp_s4 = arg0->unk_08; - temp_s5 = arg0->unk_0C; - temp_s7 = arg0->unk_10; - temp_fp = arg0->unk_14; - - if (arg3 == 0) { - D_800A82D4 = 0; - D_800A82D8 = 0x20; - D_800A82DC = 0; - D_800A82D9 = 0; - sp64 = 0; - sp62 = 0; - sp60 = 0; - } else { - D_800A82D4 = arg4->unk_00; - D_800A82D8 = arg4->unk_04; - D_800A82DC = arg4->unk_08; - D_800A82D9 = arg4->unk_05; - sp64 = arg4->unk_0C; - sp62 = arg4->unk_0E; - sp60 = arg4->unk_10; - } - - while (arg2) { - for (i = 0; i < var_v0; i++) { - if (func_8000C4A8(temp_s4, temp_s5, arg1, &sp64) != 0) { - return 2; - } - arg1 += 0x80; - } - - if (func_8000C4A8(temp_s7, temp_fp, arg1, &sp62) != 0) { - return 2; - } - - arg1 += 0x80; - - if (func_8000C4A8(temp_s7, temp_fp, arg1, &sp60) != 0) { - return 2; - } - - arg2--; - arg1 += 0x80; - - arg1 += (sp58 * 2); - } - - arg4->unk_00 = D_800A82D4; - arg4->unk_04 = D_800A82D8; - arg4->unk_08 = D_800A82DC; - arg4->unk_05 = D_800A82D9; - arg4->unk_0C = sp64; - arg4->unk_0E = sp62; - arg4->unk_10 = sp60; - - return 0; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/CE80/func_8000C280.s") -#endif - -#ifdef NON_MATCHING -s32 func_8000C4A8(JpegHuffmanTable* arg0, JpegHuffmanTable* arg1, s16* arg2, s16* arg3) { - s8 i; - s8 sp36; - s16 sp34; - u32 test; - - if (func_8000C644(arg0, &sp34, &sp36) != 0) { - return 1; - } - - *arg3 += sp34; - *arg2 = *arg3; - i = 1; - - while (i < 0x40) { - if (func_8000C644(arg1, &sp34, &sp36) != 0) { - return 1; - } - - if (sp34 == 0) { - if (sp36 == 0xF) { - while (sp36 >= 0) { - sp36--; - arg2[i++] = 0; - } - continue; - } - - while (i < 0x40) { - arg2[i++] = 0; - } - break; - } - - while (sp36-- > 0) { - arg2[i++] = 0; - } - - arg2[i++] = sp34; - } - - return 0; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/CE80/func_8000C4A8.s") -#endif - -typedef struct sp24_func_8000C644 { - u16 unk_00; - u8 unk_02; -} sp24_func_8000C644; - -#ifdef NON_MATCHING -s32 func_8000C644(JpegHuffmanTable* arg0, s16* arg1, s8* arg2) { - u8 i; - sp24_func_8000C644 sp24; - s16 temp_v0; - - sp24.unk_00 = 0; - temp_v0 = func_8000C780(0x10); - - for (i = 0; i < 16; i++) { - sp24.unk_00 = temp_v0 >> (0xF - i); - - if ((arg0->codesB[i] != 0xFFFF) && !(arg0->codesB[i] < sp24.unk_00)) { - break; - } - } - - if (i >= 16) { - return 1; - } - - 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; - *arg1 = 0; - - if ((sp24.unk_02 & 0xF) != 0) { - sp24.unk_02 &= 0xF; - - *arg1 = func_8000C780(sp24.unk_02); - if (*arg1 < (1 << (sp24.unk_02 + 0x1F))) { - *arg1 += (-1 << sp24.unk_02) + 1; - } - } - - return 0; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/CE80/func_8000C644.s") -#endif - -#ifdef NON_MATCHING -u16 func_8000C780(u8 arg0) { - u8 var_v0; - u8 var_v1; - u32 ret; - - var_v0 = D_800A82D8 >> 3; - - while (var_v0 > 0) { - var_v1 = D_800A82D0[D_800A82D4++]; - - if ((D_800A82D9 != 0) && (var_v1 == 0)) { - var_v1 = D_800A82D0[D_800A82D4++]; - } - - if (var_v1 == 0xFF) { - D_800A82D9 = 1; - } else { - D_800A82D9 = 0; - } - - D_800A82DC <<= 8; - D_800A82DC |= var_v1; - D_800A82D8 -= 8; - - var_v0--; - } - - ret = (D_800A82DC << D_800A82D8); - D_800A82D8 += arg0; - - ret >>= -arg0; - return ret; -} -#else -#pragma GLOBAL_ASM("asm/us/nonmatchings/CE80/func_8000C780.s") -#endif diff --git a/src/CE80.h b/src/CE80.h deleted file mode 100644 index db01d13..0000000 --- a/src/CE80.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _CE80_H_ -#define _CE80_H_ - -#include "global.h" -#include "jpegutils.h" - -typedef struct unk_func_80003680_sp27 { - /* 0x00 */ s32 unk_00; - /* 0x04 */ u8 unk_04; - /* 0x05 */ u8 unk_05; - /* 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 - -typedef struct unk_func_80003680_sp60 { - /* 0x00 */ s32 unk_00; - /* 0x04 */ u8 unk_04; - /* 0x05 */ u8 unk_05; - /* 0x08 */ s32 unk_08; - /* 0x0C */ s16 unk_0C; - /* 0x0E */ s16 unk_0E; - /* 0x10 */ s16 unk_10; -} unk_func_80003680_sp60; // size = 0x14 - -s32 func_8000C280(unk_func_80003680_sp27*, u32, u32, u8, unk_func_80003680_sp60*); -s32 func_8000C4A8(JpegHuffmanTable*, JpegHuffmanTable*, s16*, s16*); -s32 func_8000C644(JpegHuffmanTable*, s16*, s8*); -u16 func_8000C780(u8); - -#endif // _CE80_H_ diff --git a/src/jpeg_decoder.c b/src/jpeg_decoder.c new file mode 100644 index 0000000..145bd33 --- /dev/null +++ b/src/jpeg_decoder.c @@ -0,0 +1,191 @@ +#include "jpegutils.h" +#include "jpeg_decoder.h" + +u8* sJpegBitStreamPtr; +u32 sJpegBitStreamByteIdx; +u8 sJpegBitStreamBitIdx; +u8 sJpegBitStreamDontSkip; +u32 sJpegBitStreamCurWord; + +s32 JpegDecoder_Decode(JpegDecoder* decoder, u16* mcuBuff, s32 count, u8 isFollowing, JpegDecoderState* state) { + s16 pad; + s16 unk0; + s16 unk1; + s16 unk2; + u32 idx; + s32 inc; + u16 unkCount; + + JpegHuffmanTable* hTable0; + JpegHuffmanTable* hTable1; + JpegHuffmanTable* hTable2; + JpegHuffmanTable* hTable3; + + inc = 0; + sJpegBitStreamPtr = decoder->imageData; + if (decoder->mode == 0) { + unkCount = 2; + } else { + unkCount = 4; + if (decoder->unk_05 == 1) { + inc = 8 * 8 * 2; + } + } + + hTable0 = decoder->hTablePtrs[0]; + hTable1 = decoder->hTablePtrs[1]; + hTable2 = decoder->hTablePtrs[2]; + hTable3 = decoder->hTablePtrs[3]; + + if (!isFollowing) { + sJpegBitStreamByteIdx = 0; + sJpegBitStreamBitIdx = 32; + sJpegBitStreamCurWord = 0; + sJpegBitStreamDontSkip = 0; + unk0 = 0; + unk1 = 0; + unk2 = 0; + } else { + sJpegBitStreamByteIdx = state->byteIdx; + sJpegBitStreamBitIdx = state->bitIdx; + sJpegBitStreamCurWord = state->curWord; + sJpegBitStreamDontSkip = state->dontSkip; + unk0 = state->unk_0C; + unk1 = state->unk_0E; + unk2 = state->unk_10; + } + + while (count != 0) { + for (idx = 0; idx < unkCount; idx++) { + if (JpegDecoder_ProcessMcu(hTable0, hTable1, mcuBuff, &unk0)) { + return 2; + } + mcuBuff += 8 * 8; + } + + if (JpegDecoder_ProcessMcu(hTable2, hTable3, mcuBuff, &unk1)) { + return 2; + } + mcuBuff += 8 * 8; + + if (JpegDecoder_ProcessMcu(hTable2, hTable3, mcuBuff, &unk2)) { + return 2; + } + + count--; + mcuBuff += 8 * 8; + mcuBuff += inc; + } + + state->byteIdx = sJpegBitStreamByteIdx; + state->bitIdx = sJpegBitStreamBitIdx; + state->curWord = sJpegBitStreamCurWord; + state->dontSkip = sJpegBitStreamDontSkip; + state->unk_0C = unk0; + state->unk_0E = unk1; + state->unk_10 = unk2; + return 0; +} + +s32 JpegDecoder_ProcessMcu(JpegHuffmanTable* hTable0, JpegHuffmanTable* hTable1, u16* mcu, s16* unk) { + s8 i = 0; + s8 zeroCount; + s16 coeff; + + if (JpegDecoder_ParseNextSymbol(hTable0, &coeff, &zeroCount)) { + return 1; + } + + *unk += coeff; + mcu[i++] = *unk; + while (i < 8 * 8) { + if (JpegDecoder_ParseNextSymbol(hTable1, &coeff, &zeroCount) != 0) { + return 1; + } + + if (coeff == 0) { + if (zeroCount == 0xF) { + while (zeroCount-- >= 0) { + mcu[i++] = 0; + } + } else { + while (i < 8 * 8) { + mcu[i++] = 0; + } + break; + } + } else { + while (0 < zeroCount--) { + mcu[i++] = 0; + } + mcu[i++] = coeff; + } + } + + return 0; +} + +s32 JpegDecoder_ParseNextSymbol(JpegHuffmanTable* hTable, s16* outCoeff, s8* outZeroCount) { + u8 codeIdx; + u8 sym; + u16 codeOff = 0; + u16 buff = JpegDecoder_ReadBits(16); + + for (codeIdx = 0; codeIdx < 16; codeIdx++) { + if (hTable->codesB[codeIdx] == 0xFFFF) { + continue; + } + + codeOff = buff >> (15 - codeIdx); + if (codeOff <= hTable->codesB[codeIdx]) { + break; + } + } + + if (codeIdx >= 16) { + return 1; + } + + sym = hTable->symbols[hTable->codeOffs[codeIdx] + codeOff - hTable->codesA[codeIdx]]; + *outZeroCount = sym >> 4; + sym &= 0xF; + + sJpegBitStreamBitIdx += codeIdx - 15; + *outCoeff = 0; + if (sym) { + *outCoeff = JpegDecoder_ReadBits(sym); + if (*outCoeff < (1 << (sym - 1))) { + *outCoeff += (-1U << sym) + 1; + } + } + + return 0; +} + +u16 JpegDecoder_ReadBits(u8 len) { + u8 byteCount; + u8 data; + s32 ret = 0; + u32 temp; + + for (byteCount = sJpegBitStreamBitIdx >> 3; byteCount > 0; byteCount--) { + data = sJpegBitStreamPtr[sJpegBitStreamByteIdx++]; + if (sJpegBitStreamDontSkip) { + if (data == 0) { + data = sJpegBitStreamPtr[sJpegBitStreamByteIdx++]; + } + } + + sJpegBitStreamDontSkip = (data == 0xFF) ? 1 : 0; + + sJpegBitStreamCurWord <<= 8; + sJpegBitStreamCurWord |= data; + sJpegBitStreamBitIdx -= 8; + } + + ret = sJpegBitStreamCurWord << sJpegBitStreamBitIdx; + temp = ret; + ret = temp >> -len; + sJpegBitStreamBitIdx += len; + return ret; +} diff --git a/src/jpeg_decoder.h b/src/jpeg_decoder.h new file mode 100644 index 0000000..8d7aa39 --- /dev/null +++ b/src/jpeg_decoder.h @@ -0,0 +1,67 @@ +#ifndef JPEG_DECODER_H +#define JPEG_DECODER_H + +#include "global.h" +#include "jpegutils.h" + +typedef union JpegTaskData { + struct { + /* 0x00 */ u32 address; + /* 0x04 */ u32 mbCount; + /* 0x08 */ u32 mode; + /* 0x0C */ u32 qTableYPtr; + /* 0x10 */ u32 qTableUPtr; + /* 0x14 */ u32 qTableVPtr; + /* 0x18 */ u32 mbSize; // This field is used by the microcode to save the macroblock size during a yield + }; + long long int force_structure_alignment; +} JpegTaskData; // size = 0x20 + +typedef struct JpegWork { + /* 0x000 */ JpegTaskData taskData; + /* 0x020 */ u64 yieldData[0x200 / sizeof(u64)]; + /* 0x220 */ JpegQuantizationTable qTableY; + /* 0x2A0 */ JpegQuantizationTable qTableU; + /* 0x320 */ JpegQuantizationTable qTableV; + /* 0x3A0 */ u8 codesLengths[0x110]; + /* 0x4B0 */ u16 codes[0x108]; + /* 0x6C0 */ u16 data[4][0x180]; +} JpegWork; // size = 0x12C0 + +typedef struct JpegDecoder { + /* 0x00 */ void* imageData; + /* 0x04 */ u8 mode; + /* 0x05 */ u8 unk_05; + /* 0x08 */ JpegHuffmanTable* hTablePtrs[4]; + /* 0x18 */ u8 unk_18; +} JpegDecoder; // size = 0x1C + +typedef struct JpegContext { + /* 0x00 */ u8 dqtCount; + /* 0x04 */ u8* dqtPtr[3]; + /* 0x10 */ u8 dhtCount; + /* 0x14 */ u8* dhtPtr[4]; + /* 0x24 */ void* imageData; + /* 0x28 */ u32 mode; // 0 if Y V0 is 1 and 2 if Y V0 is 2 + /* 0x30 */ OSScTask scTask; + /* 0x98 */ OSMesgQueue mq; + /* 0xB0 */ OSMesg msg; + /* 0xB4 */ JpegWork* workBuf; +} JpegContext; // size = 0xB8 + +typedef struct JpegDecoderState { + /* 0x00 */ u32 byteIdx; + /* 0x04 */ u8 bitIdx; + /* 0x05 */ u8 dontSkip; + /* 0x08 */ u32 curWord; + /* 0x0C */ s16 unk_0C; + /* 0x0E */ s16 unk_0E; + /* 0x10 */ s16 unk_10; +} JpegDecoderState; // size = 0x14 + +s32 JpegDecoder_Decode(JpegDecoder*, u16*, s32, u8, JpegDecoderState*); +s32 JpegDecoder_ProcessMcu(JpegHuffmanTable*, JpegHuffmanTable*, u16*, s16*); +s32 JpegDecoder_ParseNextSymbol(JpegHuffmanTable*, s16*, s8*); +u16 JpegDecoder_ReadBits(u8); + +#endif // JPEG_DECODER_H diff --git a/src/jpegutils.c b/src/jpegutils.c index b0f41de..0f0b26b 100644 --- a/src/jpegutils.c +++ b/src/jpegutils.c @@ -156,4 +156,4 @@ u32 JpegUtils_ProcessHuffmanTableImplOld(u8* dht, JpegHuffmanTableOld* ht, u8* c JpegUtils_SetHuffmanTableOld(dht + 0x10, ht, codesLengths, codes, count2, isAc); return 0; -} \ No newline at end of file +} diff --git a/yamls/us/rom.yaml b/yamls/us/rom.yaml index a82c4a7..661b0be 100644 --- a/yamls/us/rom.yaml +++ b/yamls/us/rom.yaml @@ -48,7 +48,7 @@ - [0xC4B0, c, libleo/bootdisk] - [0xC910, hasm, ../../src/libleo/bootstrap] - [0xC970, c, jpegutils] - - [0xCE80, c] # + - [0xCE80, c, jpeg_decoder] - [0xD470, c] # - [0xDDC0, c] - [0xE1C0, c] # load gb emulator (fragment 1) @@ -505,7 +505,8 @@ - {vram: 0x800A7450, type: .bss, name: stage_loader} - {vram: 0x800A74C0, type: .bss, name: crash_screen} - {vram: 0x800A7EA0, type: .bss, name: profiler} - - {vram: 0x800A8100, type: bss, name: unk_bss_2} + - {vram: 0x800A8100, type: bss, name: unk_bss_2} + - {vram: 0x800A82D0, type: .bss, name: jpeg_decoder} - {vram: 0x800A82E0, type: .bss, name: D470} - {vram: 0x800A83A0, type: bss, name: unk_bss_17} - {vram: 0x800AA680, type: .bss, name: E890}