summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
authorengineer124 <engineer124engineer124@gmail.com>2021-11-20 09:35:46 +1100
committerengineer124 <engineer124engineer124@gmail.com>2021-11-20 09:35:46 +1100
commitf0c676d12422acac4844c4e6ed21abe511ae45a1 (patch)
tree3ac70ad2404767670c8f8ba7c10d9095cc6a9db1 /src/code
parent65cbbf40fdb5ce2f50057334dda7e353920dffa1 (diff)
parentdfdbd66106ba77c21ccfaa91e9b0c52d4364121b (diff)
Merge branch 'audio_bgm' into voice
Diffstat (limited to 'src/code')
-rw-r--r--src/code/audio/code_8019AF00.c2
-rw-r--r--src/code/code_8010C1B0.c2
-rw-r--r--src/code/code_801AA020.c9
-rw-r--r--src/code/jpegdecoder.c193
-rw-r--r--src/code/jpegutils.c156
-rw-r--r--src/code/z_common_data.c4
-rw-r--r--src/code/z_game_over.c4
-rw-r--r--src/code/z_jpeg.c305
-rw-r--r--src/code/z_scene.c2
9 files changed, 646 insertions, 31 deletions
diff --git a/src/code/audio/code_8019AF00.c b/src/code/audio/code_8019AF00.c
index 227384d0a..9354af188 100644
--- a/src/code/audio/code_8019AF00.c
+++ b/src/code/audio/code_8019AF00.c
@@ -296,7 +296,7 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A2D54.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A2DE0.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/Audio_IsSequencePlaying.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/code_8019AF00/func_801A2E54.s")
diff --git a/src/code/code_8010C1B0.c b/src/code/code_8010C1B0.c
index 12e0eadb4..2c1fd410f 100644
--- a/src/code/code_8010C1B0.c
+++ b/src/code/code_8010C1B0.c
@@ -1,7 +1,7 @@
#include "global.h"
// Blocks the current thread until all currently queued scheduler tasks have been completed
-void func_8010C1B0(void) {
+void MsgEvent_SendNullTask(void) {
OSScTask task;
OSMesgQueue queue;
OSMesg msg;
diff --git a/src/code/code_801AA020.c b/src/code/code_801AA020.c
deleted file mode 100644
index 6cefc66d9..000000000
--- a/src/code/code_801AA020.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "global.h"
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_801AA020/func_801AA020.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_801AA020/func_801AA248.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_801AA020/func_801AA3E4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_801AA020/func_801AA520.s")
diff --git a/src/code/jpegdecoder.c b/src/code/jpegdecoder.c
new file mode 100644
index 000000000..336e381f9
--- /dev/null
+++ b/src/code/jpegdecoder.c
@@ -0,0 +1,193 @@
+#include "z64jpeg.h"
+#include "libc/stdbool.h"
+#include "macros.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 true;
+ }
+
+ *unk += coeff;
+ mcu[i++] = *unk;
+ while (i < 8 * 8) {
+ if (JpegDecoder_ParseNextSymbol(hTable1, &coeff, &zeroCount)) {
+ return true;
+ }
+
+ 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 false;
+}
+
+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 < ARRAY_COUNT(hTable->codesB); codeIdx++) {
+ if (hTable->codesB[codeIdx] == 0xFFFF) {
+ continue;
+ }
+
+ codeOff = buff >> (15 - codeIdx);
+ if (codeOff <= hTable->codesB[codeIdx]) {
+ break;
+ }
+ }
+
+ if (codeIdx >= ARRAY_COUNT(hTable->codesB)) {
+ return true;
+ }
+
+ 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 += (-1 << sym) + 1;
+ }
+ }
+
+ return false;
+}
+
+u16 JpegDecoder_ReadBits(u8 len) {
+ u8 byteCount;
+ u8 data;
+ s32 ret;
+ u32 temp;
+ ret = 0; // this is required for some reason
+
+ for (byteCount = sJpegBitStreamBitIdx >> 3; byteCount > 0; byteCount--) {
+ data = sJpegBitStreamPtr[sJpegBitStreamByteIdx++];
+ if (sJpegBitStreamDontSkip) {
+ if (data == 0) {
+ data = sJpegBitStreamPtr[sJpegBitStreamByteIdx++];
+ }
+ }
+
+ sJpegBitStreamDontSkip = (data == 0xFF) ? true : false;
+
+ sJpegBitStreamCurWord <<= 8;
+ sJpegBitStreamCurWord |= data;
+ sJpegBitStreamBitIdx -= 8;
+ }
+
+ ret = (sJpegBitStreamCurWord << (sJpegBitStreamBitIdx));
+ temp = ret;
+ ret = temp >> -len;
+ sJpegBitStreamBitIdx += len;
+ return ret;
+}
diff --git a/src/code/jpegutils.c b/src/code/jpegutils.c
index 89ed4e97d..904643f46 100644
--- a/src/code/jpegutils.c
+++ b/src/code/jpegutils.c
@@ -1,17 +1,155 @@
-#include "global.h"
+#include "z64jpeg.h"
+#include "libc/stdbool.h"
+#include "macros.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9B10.s")
+void JpegUtils_ProcessQuantizationTable(u8* dqt, JpegQuantizationTable* qt, u8 count) {
+ u8 i;
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9B78.s")
+ for (i = 0; i < count; i++) {
+ u8 j;
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9BFC.s")
+ dqt++;
+ for (j = 0; j < ARRAY_COUNT(qt[i].table); j++) {
+ qt[i].table[j] = *dqt++;
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9C68.s")
+s32 JpegUtils_ParseHuffmanCodesLengths(u8* ptr, u8* codesLengths) {
+ u8 off = 1;
+ s16 count = 0;
+ s16 idx = 1;
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9D10.s")
+ while (off <= 16) {
+ while (idx <= ptr[off - 1]) {
+ codesLengths[count++] = off;
+ idx++;
+ }
+ idx = 1;
+ off++;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9DCC.s")
+ codesLengths[count] = 0;
+ return count;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9EA4.s")
+s32 JpegUtils_GetHuffmanCodes(u8* codesLengths, u16* codes) {
+ s16 idx = 0;
+ u16 code = 0;
+ u8 lastLen = codesLengths[0];
-#pragma GLOBAL_ASM("asm/non_matchings/code/jpegutils/func_801A9F4C.s")
+ 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;
+}
+
+s32 JpegUtils_SetHuffmanTable(u8* data, JpegHuffmanTable* ht, u16* codes) {
+ u8 idx;
+ u16 codeOff = 0;
+
+ for (idx = 0; idx < 16; 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;
+}
+
+u32 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 true;
+ }
+
+ dht += 16;
+ ht[idx].symbols = dht;
+ dht += codeCount;
+ }
+ return false;
+}
+
+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 true;
+ }
+
+ if (JpegUtils_GetHuffmanCodes(codesLengths, codes) != count2) {
+ return true;
+ }
+
+ JpegUtils_SetHuffmanTableOld(dht + 0x10, ht, codesLengths, codes, count2, isAc);
+
+ return false;
+}
diff --git a/src/code/z_common_data.c b/src/code/z_common_data.c
index 88fa3e103..26fd324a7 100644
--- a/src/code/z_common_data.c
+++ b/src/code/z_common_data.c
@@ -5,9 +5,9 @@ SaveContext gSaveContext;
void SaveContext_Init(void) {
bzero(&gSaveContext, sizeof(gSaveContext));
gSaveContext.playerForm = 0;
- gSaveContext.seqIndex = 0xFF;
+ gSaveContext.seqIndex = (u8)NA_BGM_DISABLED;
gSaveContext.nightSeqIndex = 0xFF;
- gSaveContext.unk_3F46 = 0;
+ gSaveContext.unk_3F46 = NA_BGM_GENERAL_SFX;
gSaveContext.nextCutsceneIndex = 0xFFEF;
gSaveContext.cutsceneTrigger = 0;
gSaveContext.unk_3F4D = 0;
diff --git a/src/code/z_game_over.c b/src/code/z_game_over.c
index c510c1974..979b28cba 100644
--- a/src/code/z_game_over.c
+++ b/src/code/z_game_over.c
@@ -45,7 +45,7 @@ void GameOver_Update(GlobalContext* globalCtx) {
gSaveContext.unk_3DC0 = 2000;
gSaveContext.naviTimer = 0;
- gSaveContext.seqIndex = 0xFF;
+ gSaveContext.seqIndex = (u8)NA_BGM_DISABLED;
gSaveContext.nightSeqIndex = 0xFF;
gSaveContext.eventInf[0] = 0;
gSaveContext.eventInf[1] = 0;
@@ -66,7 +66,7 @@ void GameOver_Update(GlobalContext* globalCtx) {
gameOverCtx->state = GAMEOVER_DEATH_WAIT_GROUND;
break;
case GAMEOVER_DEATH_FADE_OUT:
- if (func_801A8A50(1) != 32) {
+ if (func_801A8A50(1) != NA_BGM_GAME_OVER) {
func_80169F78(globalCtx);
if (gSaveContext.respawnFlag != -7) {
gSaveContext.respawnFlag = -6;
diff --git a/src/code/z_jpeg.c b/src/code/z_jpeg.c
index 395a45835..c611ab1f8 100644
--- a/src/code/z_jpeg.c
+++ b/src/code/z_jpeg.c
@@ -1,11 +1,304 @@
-#include "global.h"
+#include "z64jpeg.h"
+#include "libc/stdbool.h"
+#include "variables.h"
+#include "functions.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_jpeg/func_800F42A0.s")
+#define MARKER_ESCAPE 0x00
+#define MARKER_SOI 0xD8
+#define MARKER_SOF 0xC0
+#define MARKER_DHT 0xC4
+#define MARKER_DQT 0xDB
+#define MARKER_DRI 0xDD
+#define MARKER_SOS 0xDA
+#define MARKER_APP0 0xE0
+#define MARKER_APP1 0xE1
+#define MARKER_APP2 0xE2
+#define MARKER_COM 0xFE
+#define MARKER_EOI 0xD9
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_jpeg/func_800F43BC.s")
+/**
+ * Configures and schedules a JPEG decoder task and waits for it to finish.
+ */
+void Jpeg_ScheduleDecoderTask(JpegContext* jpegCtx) {
+ static OSTask_t sJpegTask = {
+ M_NJPEGTASK, // type
+ 0, // flags
+ NULL, // ucode_boot
+ 0, // ucode_boot_size
+ gJpegUCode, // ucode
+ 0x1000, // ucode_size
+ gJpegUCodeData, // ucode_data
+ 0x800, // ucode_data_size
+ NULL, // dram_stack
+ 0, // dram_stack_size
+ NULL, // output_buff
+ NULL, // output_buff_size
+ NULL, // data_ptr
+ sizeof(JpegTaskData), // data_size
+ NULL, // yield_data_ptr
+ 0x200, // yield_data_size
+ };
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_jpeg/func_800F44F4.s")
+ JpegWork* workBuf = jpegCtx->workBuf;
+ s32 pad[2];
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_jpeg/func_800F4540.s")
+ workBuf->taskData.address = &workBuf->data;
+ workBuf->taskData.mode = jpegCtx->mode;
+ workBuf->taskData.mbCount = 4;
+ workBuf->taskData.qTableYPtr = &workBuf->qTableY;
+ workBuf->taskData.qTableUPtr = &workBuf->qTableU;
+ workBuf->taskData.qTableVPtr = &workBuf->qTableV;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_jpeg/func_800F470C.s")
+ sJpegTask.flags = 0;
+ sJpegTask.ucodeBoot = SysUcode_GetUCodeBoot();
+ sJpegTask.ucodeBootSize = SysUcode_GetUCodeBootSize();
+ sJpegTask.yieldDataPtr = (u64*)&workBuf->yieldData;
+ sJpegTask.dataPtr = (u64*)&workBuf->taskData;
+
+ jpegCtx->scTask.next = NULL;
+ jpegCtx->scTask.flags = OS_SC_NEEDS_RSP;
+ jpegCtx->scTask.msgQ = &jpegCtx->mq;
+ jpegCtx->scTask.msg = NULL;
+ jpegCtx->scTask.framebuffer = NULL;
+ jpegCtx->scTask.list.t = sJpegTask;
+
+ osSendMesg(&gSchedContext.cmdQ, (OSMesg)&jpegCtx->scTask, OS_MESG_BLOCK);
+ Sched_SendEntryMsg(&gSchedContext); // osScKickEntryMsg
+ osRecvMesg(&jpegCtx->mq, NULL, OS_MESG_BLOCK);
+}
+
+/**
+ * Copies a 16x16 block of decoded image data to the Z-buffer.
+ */
+void Jpeg_CopyToZbuffer(u16* src, u16* zbuffer, s32 x, s32 y) {
+ u16* dst = zbuffer + (((y * SCREEN_WIDTH) + x) * 16);
+ s32 i;
+
+ for (i = 0; i < 16; i++) {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst[2] = src[2];
+ dst[3] = src[3];
+ dst[4] = src[4];
+ dst[5] = src[5];
+ dst[6] = src[6];
+ dst[7] = src[7];
+ dst[8] = src[8];
+ dst[9] = src[9];
+ dst[10] = src[10];
+ dst[11] = src[11];
+ dst[12] = src[12];
+ dst[13] = src[13];
+ dst[14] = src[14];
+ dst[15] = src[15];
+
+ src += 16;
+ dst += SCREEN_WIDTH;
+ }
+}
+
+/**
+ * Reads an u16 from a possibly unaligned address in memory.
+ *
+ * Replaces unaligned 16-bit reads with a pair of aligned reads, allowing for reading the possibly
+ * unaligned values in JPEG header files.
+ */
+u16 Jpeg_GetUnalignedU16(u8* ptr) {
+ if (((u32)ptr & 1) == 0) {
+ // Read the value normally if it's aligned to a 16-bit address.
+ return *(u16*)ptr;
+ } else {
+ // Read unaligned values using two separate aligned memory accesses when it's not.
+ return *(u16*)(ptr - 1) << 8 | (*(u16*)(ptr + 1) >> 8);
+ }
+}
+
+/**
+ * Parses the markers in the JPEG file, storing information such as the pointer to the image data
+ * in `jpegCtx` for later processing.
+ */
+void Jpeg_ParseMarkers(u8* ptr, JpegContext* jpegCtx) {
+ u32 exit = false;
+
+ jpegCtx->dqtCount = 0;
+ jpegCtx->dhtCount = 0;
+
+ while (true) {
+ if (exit) {
+ break;
+ }
+
+ // 0xFF indicates the start of a JPEG marker, so look for the next.
+ if (*ptr++ == 0xFF) {
+ switch (*ptr++) {
+ case MARKER_ESCAPE: {
+ // Compressed value 0xFF is stored as 0xFF00 to escape it, so ignore it.
+ break;
+ }
+ case MARKER_SOI: {
+ // Start of Image
+ break;
+ }
+ case MARKER_APP0: {
+ // Application marker for JFIF
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_APP1: {
+ // Application marker for EXIF
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_APP2: {
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_DQT: {
+ // Define Quantization Table, stored for later processing
+ jpegCtx->dqtPtr[jpegCtx->dqtCount++] = ptr + 2;
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_DHT: {
+ // Define Huffman Table, stored for later processing
+ jpegCtx->dhtPtr[jpegCtx->dhtCount++] = ptr + 2;
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_DRI: {
+ // Define Restart Interval
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_SOF: {
+ // Start of Frame, stores important metadata of the image.
+ // Only used for extracting the sampling factors (jpegCtx->mode).
+
+ if (ptr[9] == 0x21) {
+ // component Y : V0 == 1
+ jpegCtx->mode = 0;
+ } else if (ptr[9] == 0x22) {
+ // component Y : V0 == 2
+ jpegCtx->mode = 2;
+ }
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ case MARKER_SOS: {
+ // Start of Scan marker, indicates the start of the image data.
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ jpegCtx->imageData = ptr;
+ break;
+ }
+ case MARKER_EOI: {
+ // End of Image
+ exit = true;
+ break;
+ }
+ default: {
+ ptr += Jpeg_GetUnalignedU16(ptr);
+ break;
+ }
+ }
+ }
+ }
+}
+
+s32 Jpeg_Decode(void* data, void* zbuffer, void* work, u32 workSize) {
+ s32 y;
+ s32 x;
+ s32 j;
+ s32 i;
+ JpegContext jpegCtx;
+ JpegHuffmanTable hTables[4];
+ JpegDecoder decoder;
+ JpegDecoderState state;
+ JpegWork* workBuff = work;
+
+ if (workSize < sizeof(JpegWork)) {
+ return -1;
+ }
+
+ osCreateMesgQueue(&jpegCtx.mq, &jpegCtx.msg, 1);
+ MsgEvent_SendNullTask();
+
+ jpegCtx.workBuf = workBuff;
+
+ Jpeg_ParseMarkers(data, &jpegCtx);
+
+ switch (jpegCtx.dqtCount) {
+ case 1:
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[0], &workBuff->qTableY, 3);
+ break;
+
+ case 2:
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[0], &workBuff->qTableY, 1);
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[1], &workBuff->qTableU, 1);
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[1], &workBuff->qTableV, 1);
+ break;
+
+ case 3:
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[0], &workBuff->qTableY, 1);
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[1], &workBuff->qTableU, 1);
+ JpegUtils_ProcessQuantizationTable(jpegCtx.dqtPtr[2], &workBuff->qTableV, 1);
+ break;
+
+ default:
+ return -1;
+ }
+
+ switch (jpegCtx.dhtCount) {
+ case 1:
+ if (JpegUtils_ProcessHuffmanTable(jpegCtx.dhtPtr[0], &hTables[0], workBuff->codesLengths, workBuff->codes,
+ 4)) {
+ return -1;
+ }
+ break;
+
+ case 4:
+ // This chained if-else has printfs inside it on debug
+ if (JpegUtils_ProcessHuffmanTable(jpegCtx.dhtPtr[0], &hTables[0], workBuff->codesLengths, workBuff->codes,
+ 1)) {
+ } else if (JpegUtils_ProcessHuffmanTable(jpegCtx.dhtPtr[1], &hTables[1], workBuff->codesLengths,
+ workBuff->codes, 1)) {
+ } else if (JpegUtils_ProcessHuffmanTable(jpegCtx.dhtPtr[2], &hTables[2], workBuff->codesLengths,
+ workBuff->codes, 1)) {
+ } else if (!JpegUtils_ProcessHuffmanTable(jpegCtx.dhtPtr[3], &hTables[3], workBuff->codesLengths,
+ workBuff->codes, 1)) {
+ break;
+ }
+ return -1;
+
+ default:
+ return -1;
+ }
+
+ decoder.imageData = jpegCtx.imageData;
+ decoder.mode = jpegCtx.mode;
+ decoder.unk_05 = 2;
+
+ decoder.hTablePtrs[0] = &hTables[0];
+ decoder.hTablePtrs[1] = &hTables[1];
+ decoder.hTablePtrs[2] = &hTables[2];
+ decoder.hTablePtrs[3] = &hTables[3];
+ decoder.unk_18 = 0;
+
+ x = y = 0;
+ for (i = 0; i < 300; i += 4) {
+ if (!JpegDecoder_Decode(&decoder, (u16*)workBuff->data, 4, (i != 0), &state)) {
+ Jpeg_ScheduleDecoderTask(&jpegCtx);
+
+ for (j = 0; j < 4; j++) {
+ Jpeg_CopyToZbuffer(workBuff->data[j], zbuffer, x, y);
+ x++;
+
+ if (x >= 20) {
+ x = 0;
+ y++;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/src/code/z_scene.c b/src/code/z_scene.c
index dd158ac07..293a9762d 100644
--- a/src/code/z_scene.c
+++ b/src/code/z_scene.c
@@ -449,7 +449,7 @@ void Scene_HeaderCmdSoundSettings(GlobalContext* globalCtx, SceneCmd* cmd) {
globalCtx->soundCtx.seqIndex = cmd->soundSettings.musicSeq;
globalCtx->soundCtx.nightSeqIndex = cmd->soundSettings.nighttimeSFX;
- if (gSaveContext.seqIndex == 0xFF || func_801A8A50(0) == 0x57) {
+ if (gSaveContext.seqIndex == (u8)NA_BGM_DISABLED || func_801A8A50(0) == NA_BGM_FINAL_HOURS) {
audio_setBGM(cmd->soundSettings.bgmId);
}
}