[jak3] Avoid language 255 issue (#3818)

In Jak 3, the default PC settings file would have a language of 255
because it runs before the first settings update. This would cause the
game to crash the second time it is started.

I also added this simple imgui window to see the names of streams in the
"SPU" memory, which has been useful for debugging

![image](https://github.com/user-attachments/assets/0a9d6af7-c423-4d8a-a461-faf45e350f33)

---------

Co-authored-by: water111 <awaterford1111445@gmail.com>
This commit is contained in:
water111
2025-01-04 11:39:28 -05:00
committed by GitHub
parent ea61985e21
commit 266b423efa
5 changed files with 117 additions and 1 deletions
@@ -6,6 +6,7 @@
#include "game/graphics/display.h"
#include "game/graphics/gfx.h"
#include "game/graphics/screenshot.h"
#include "game/overlord/jak3/dma.h"
#include "game/system/hid/sdl_util.h"
#include "fmt/core.h"
@@ -104,6 +105,7 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
ImGui::MenuItem("Profiler", nullptr, &m_draw_profiler);
ImGui::MenuItem("Small Profiler", nullptr, &small_profiler);
ImGui::MenuItem("Loader", nullptr, &m_draw_loader);
ImGui::MenuItem("Overlord", nullptr, &m_draw_overlord);
if (ImGui::MenuItem("Reboot In Debug Mode!")) {
want_reboot_in_debug = true;
}
@@ -215,4 +217,19 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
if (m_draw_frame_time) {
m_frame_timer.draw_window(dma_stats);
}
if (should_draw_overlord_debug()) {
draw_overlord_debug_menu();
}
}
void OpenGlDebugGui::draw_overlord_debug_menu() {
ImGui::Begin("Overlord");
for (int stream_idx = 0; stream_idx < 6; stream_idx++) {
auto& stream = jak3::g_overlord_stream_memory.infos[stream_idx];
ImGui::Text("%30s [%3d] | %30s [%3d]", stream[0].name.chars, stream[0].idx,
stream[1].name.chars, stream[1].idx);
}
}
@@ -50,6 +50,7 @@ class OpenGlDebugGui {
bool should_draw_subtitle_editor() const { return master_enable && m_subtitle_editor; }
bool should_draw_filters_menu() const { return master_enable && m_filters_menu; }
bool should_draw_loader_menu() const { return master_enable && m_draw_loader; }
bool should_draw_overlord_debug() const { return master_enable && m_draw_overlord; }
bool should_advance_frame() { return m_frame_timer.should_advance_frame(); }
bool should_gl_finish() const { return m_frame_timer.do_gl_finish; }
@@ -72,11 +73,13 @@ class OpenGlDebugGui {
bool master_enable = false;
private:
void draw_overlord_debug_menu();
FrameTimeRecorder m_frame_timer;
bool m_draw_frame_time = false;
bool m_draw_profiler = false;
bool m_draw_debug = false;
bool m_draw_loader = false;
bool m_draw_overlord = false;
bool m_subtitle_editor = false;
bool m_filters_menu = false;
bool m_want_screenshot = false;
+74
View File
@@ -13,6 +13,7 @@
#define VOICE_BIT(voice) (1 << ((voice) >> 1))
namespace jak3 {
OverlordStreamMemory g_overlord_stream_memory;
using namespace iop;
namespace {
@@ -51,6 +52,8 @@ struct DmaInterruptHandlerHack {
bool pending = false;
} g_DmaInterruptHack;
const char* g_current_stream_name = 0;
} // namespace
void jak3_overlord_init_globals_dma() {
@@ -139,10 +142,74 @@ int voice_trans_wrapper(s16 chan, u32 mode, const void* iop_addr, u32 spu_addr,
} else {
g_voiceTransRunning = true;
g_voiceTransTime = GetSystemTimeLow();
switch (spu_addr) {
case 0x5040:
g_overlord_stream_memory.update_name(g_current_stream_name, 0, 0);
break;
case 0x7040:
g_overlord_stream_memory.update_name(g_current_stream_name, 0, 1);
break;
case 0x9080:
g_overlord_stream_memory.update_name(g_current_stream_name, 1, 0);
break;
case 0xb080:
g_overlord_stream_memory.update_name(g_current_stream_name, 1, 1);
break;
case 0xd0c0:
g_overlord_stream_memory.update_name(g_current_stream_name, 2, 0);
break;
case 0xf0c0:
g_overlord_stream_memory.update_name(g_current_stream_name, 2, 1);
break;
case 0x11100:
g_overlord_stream_memory.update_name(g_current_stream_name, 3, 0);
break;
case 0x13100:
g_overlord_stream_memory.update_name(g_current_stream_name, 3, 1);
break;
case 0x15140:
g_overlord_stream_memory.update_name(g_current_stream_name, 4, 0);
break;
case 0x17140:
g_overlord_stream_memory.update_name(g_current_stream_name, 4, 1);
break;
case 0x19180:
g_overlord_stream_memory.update_name(g_current_stream_name, 5, 0);
break;
case 0x1b180:
g_overlord_stream_memory.update_name(g_current_stream_name, 5, 1);
break;
}
return sceSdVoiceTrans(chan, mode, iop_addr, spu_addr, size);
}
}
OverlordStreamMemory::OverlordStreamMemory() {
for (auto& x : infos) {
for (auto& y : x) {
y.idx = 0;
strcpy(y.name.chars, "Uninitialized");
}
}
}
void OverlordStreamMemory::update_name(const char* input, int stream, int side) {
auto& info = infos[stream][side];
if (!input) {
strcpy(info.name.chars, "???");
info.idx = 0;
} else {
if (strcmp(input, info.name.chars) == 0) {
info.idx++;
} else {
info.idx = 0;
strncpy(info.name.chars, input, 48);
info.name.chars[47] = 0;
}
}
}
u32 read_rate_calc(u32 pitch) {
u64 pitch1 = (pitch >> 3);
u64 mult_result = pitch1 * 0x2492'4925ull;
@@ -464,6 +531,13 @@ int DMA_SendToSPUAndSync(const u8* iop_mem,
ovrld_log(LogCategory::SPU_DMA_STR,
"DMA to SPU requested for {}, {} bytes to 0x{:x}, currently busy? {}",
cmd ? cmd->name : "NO-CMD", length, spu_addr, g_bSpuDmaBusy);
if (cmd) {
g_current_stream_name = cmd->name;
} else {
const static char* unknown = "unknown";
g_current_stream_name = unknown;
}
if (g_bSpuDmaBusy == 0) {
// not busy, we can actually start dma now.
g_nSpuDmaChannel = snd_GetFreeSPUDMA();
+16
View File
@@ -2,6 +2,8 @@
#include "common/common_types.h"
#include "game/overlord/jak3/rpc_interface.h"
namespace jak3 {
void jak3_overlord_init_globals_dma();
struct ISO_VAGCommand;
@@ -29,4 +31,18 @@ struct DmaQueueEntry {
u32 num_isobuffered_chunks = 0;
};
void dma_intr_hack();
struct OverlordStreamMemory {
struct Info {
SoundStreamName name;
int idx = 0;
};
Info infos[6][2];
OverlordStreamMemory();
void update_name(const char* input, int stream, int side);
};
extern OverlordStreamMemory g_overlord_stream_memory;
} // namespace jak3
+7 -1
View File
@@ -249,7 +249,13 @@
)
(defmethod get-game-language ((obj pc-settings-jak3))
(get-current-language)
;; if the language is unintialized, return the default
(let ((lang (get-current-language)))
(if (= lang 255)
(scf-get-language)
lang
)
)
)