diff --git a/config/RSBE01_02/splits.txt b/config/RSBE01_02/splits.txt index 8c45f1f..73be664 100644 --- a/config/RSBE01_02/splits.txt +++ b/config/RSBE01_02/splits.txt @@ -20,6 +20,10 @@ sora/mt/mt_prng.cpp: .sbss start:0x805A00B8 end:0x805A00C0 .sdata2 start:0x805A1748 end:0x805A176C +sora/ty/ty_fig_listmng.cpp: + .text start:0x800AC9DC end:0x800AD808 + .data start:0x80455120 end:0x80455180 + sora/ac/ac_cmd_interpreter.cpp: .text start:0x80139658 end:0x8013CA1C .rodata start:0x80409520 end:0x8040964C diff --git a/config/RSBE01_02/symbols.txt b/config/RSBE01_02/symbols.txt index b30109e..1cfa11f 100644 --- a/config/RSBE01_02/symbols.txt +++ b/config/RSBE01_02/symbols.txt @@ -2479,7 +2479,7 @@ alloc__13gfHeapManagerFQ25Heaps8HeapTypeUl = .text:0x800249E4; // type:function fn_80024A00 = .text:0x80024A00; // type:function size:0x18 fn_80024A18 = .text:0x80024A18; // type:function size:0x1C fn_80024A34 = .text:0x80024A34; // type:function size:0x18 -fn_80024A4C = .text:0x80024A4C; // type:function size:0x4 +free__13gfHeapManagerFPv = .text:0x80024A4C; // type:function size:0x4 dumpAll__13gfHeapManagerFv = .text:0x80024A50; // type:function size:0xB8 dumpList__13gfHeapManagerFv = .text:0x80024B08; // type:function size:0x264 update__17gfKeepFrameBufferFv = .text:0x80024D6C; // type:function size:0x54 @@ -2983,9 +2983,9 @@ fn_80043CB0 = .text:0x80043CB0; // type:function size:0x70 fn_80043D20 = .text:0x80043D20; // type:function size:0x40 fn_80043D60 = .text:0x80043D60; // type:function size:0x4C fn_80043DAC = .text:0x80043DAC; // type:function size:0x70 -fn_80043E1C = .text:0x80043E1C; // type:function size:0x150 -fn_80043F6C = .text:0x80043F6C; // type:function size:0x40 -fn_80043FAC = .text:0x80043FAC; // type:function size:0x90 +__ct__10utRelocateFPvUl = .text:0x80043E1C; // type:function size:0x150 +__dt__10utRelocateFv = .text:0x80043F6C; // type:function size:0x40 +getPublicAddress__10utRelocateFPCc = .text:0x80043FAC; // type:function size:0x90 fn_8004403C = .text:0x8004403C; // type:function size:0xC8 fn_80044104 = .text:0x80044104; // type:function size:0x110 fn_80044214 = .text:0x80044214; // type:function size:0x34 @@ -3282,7 +3282,7 @@ fn_800526C4 = .text:0x800526C4; // type:function size:0x20 fn_800526E4 = .text:0x800526E4; // type:function size:0x20 fn_80052704 = .text:0x80052704; // type:function size:0x64 fn_80052768 = .text:0x80052768; // type:function size:0x38 -fn_800527A0 = .text:0x800527A0; // type:function size:0x38 +gmCheckExistFigure__FUs = .text:0x800527A0; // type:function size:0x38 fn_800527D8 = .text:0x800527D8; // type:function size:0x38 fn_80052810 = .text:0x80052810; // type:function size:0x38 fn_80052848 = .text:0x80052848; // type:function size:0x38 @@ -4340,26 +4340,26 @@ fn_800AB7AC = .text:0x800AB7AC; // type:function size:0x8B8 fn_800AC064 = .text:0x800AC064; // type:function size:0x940 fn_800AC9A4 = .text:0x800AC9A4; // type:function size:0x14 fn_800AC9B8 = .text:0x800AC9B8; // type:function size:0x24 -fn_800AC9DC = .text:0x800AC9DC; // type:function size:0xA8 -fn_800ACA84 = .text:0x800ACA84; // type:function size:0x7C -fn_800ACB00 = .text:0x800ACB00; // type:function size:0x98 -fn_800ACB98 = .text:0x800ACB98; // type:function size:0x8C -fn_800ACC24 = .text:0x800ACC24; // type:function size:0x1B0 -fn_800ACDD4 = .text:0x800ACDD4; // type:function size:0xC4 -fn_800ACE98 = .text:0x800ACE98; // type:function size:0xCC -fn_800ACF64 = .text:0x800ACF64; // type:function size:0xE4 -fn_800AD048 = .text:0x800AD048; // type:function size:0xE4 -fn_800AD12C = .text:0x800AD12C; // type:function size:0xC4 -fn_800AD1F0 = .text:0x800AD1F0; // type:function size:0xCC -fn_800AD2BC = .text:0x800AD2BC; // type:function size:0xE4 -fn_800AD3A0 = .text:0x800AD3A0; // type:function size:0xE4 -fn_800AD484 = .text:0x800AD484; // type:function size:0x110 -fn_800AD594 = .text:0x800AD594; // type:function size:0x40 -fn_800AD5D4 = .text:0x800AD5D4; // type:function size:0x94 -fn_800AD668 = .text:0x800AD668; // type:function size:0xAC -fn_800AD714 = .text:0x800AD714; // type:function size:0x24 -fn_800AD738 = .text:0x800AD738; // type:function size:0x74 -fn_800AD7AC = .text:0x800AD7AC; // type:function size:0x5C +__ct__20tyFigListDataManagerFb = .text:0x800AC9DC; // type:function size:0xA8 +__dt__20tyFigListDataManagerFv = .text:0x800ACA84; // type:function size:0x7C +loadRequest__20tyFigListDataManagerFv = .text:0x800ACB00; // type:function size:0x98 +isLoadFinish__20tyFigListDataManagerFv = .text:0x800ACB98; // type:function size:0x8C +setData__20tyFigListDataManagerFPvUl = .text:0x800ACC24; // type:function size:0x1B0 +getFigListSeries__20tyFigListDataManagerFlUlPUl = .text:0x800ACDD4; // type:function size:0xC4 +getPageNumSeries__20tyFigListDataManagerFl = .text:0x800ACE98; // type:function size:0xCC +nextIdSeries__20tyFigListDataManagerFUl = .text:0x800ACF64; // type:function size:0xE4 +prevIdSeries__20tyFigListDataManagerFUl = .text:0x800AD048; // type:function size:0xE4 +getFigListKind__20tyFigListDataManagerFlUlPUl = .text:0x800AD12C; // type:function size:0xC4 +getPageNumKind__20tyFigListDataManagerFl = .text:0x800AD1F0; // type:function size:0xCC +nextIdKind__20tyFigListDataManagerFUl = .text:0x800AD2BC; // type:function size:0xE4 +prevIdKind__20tyFigListDataManagerFUl = .text:0x800AD3A0; // type:function size:0xE4 +getTotalId__20tyFigListDataManagerFUlb = .text:0x800AD484; // type:function size:0x110 +getBilTexFileIdx__20tyFigListDataManagerFUl = .text:0x800AD594; // type:function size:0x40 +getBilTexFileIdxFigId__20tyFigListDataManagerFUs = .text:0x800AD5D4; // type:function size:0x94 +getBilTexFileNameFigId__20tyFigListDataManagerFUsPc = .text:0x800AD668; // type:function size:0xAC +getBilTexName__20tyFigListDataManagerFUlPc = .text:0x800AD714; // type:function size:0x24 +getBilTexNameFigId__20tyFigListDataManagerFUlPc = .text:0x800AD738; // type:function size:0x74 +getFigDataId__20tyFigListDataManagerFUl = .text:0x800AD7AC; // type:function size:0x5C fn_800AD808 = .text:0x800AD808; // type:function size:0x74 fn_800AD87C = .text:0x800AD87C; // type:function size:0x7C fn_800AD8F8 = .text:0x800AD8F8; // type:function size:0x5C diff --git a/configure.py b/configure.py index d4b1207..d21506e 100755 --- a/configure.py +++ b/configure.py @@ -287,6 +287,7 @@ def MatchingFor(*versions): "host": False, "objects": [ Object(Matching, "sora/mt/mt_prng.cpp", extra_cflags=["-RTTI off"]), + Object(NonMatching, "sora/ty/ty_fig_listmng.cpp"), Object(NonMatching, "sora/ac/ac_cmd_interpreter.cpp"), Object(Matching, "sora/ac/ac_anim_cmd_impl.cpp"), Object(Matching, "sora/ac/ac_null.cpp"), diff --git a/include/lib/BrawlHeaders b/include/lib/BrawlHeaders index 9358c5b..767d87c 160000 --- a/include/lib/BrawlHeaders +++ b/include/lib/BrawlHeaders @@ -1 +1 @@ -Subproject commit 9358c5ba8f4a199c492e986207a8a7772d54b3ec +Subproject commit 767d87c5f48ccb2b4786a2f06e6b4285f6ac6d80 diff --git a/src/sora/ty/ty_fig_listmng.cpp b/src/sora/ty/ty_fig_listmng.cpp new file mode 100644 index 0000000..384d24d --- /dev/null +++ b/src/sora/ty/ty_fig_listmng.cpp @@ -0,0 +1,345 @@ +#include +#include +#include +#include +#include +#include + +tyFigListDataManager::tyFigListDataManager(bool loadFile) { + m_isLoaded = false; + m_fileHandle.fileToLoad = 0; + m_isUnloaded = true; + if (loadFile) { + loadRequest(); + } +} + +tyFigListDataManager::~tyFigListDataManager() { + if (!m_isUnloaded) { + gfHeapManager::free(m_fileHandle.getBuffer()); + m_fileHandle.release(); + } +} + +bool tyFigListDataManager::loadRequest() { + if (m_isLoaded) { + return false; + } + m_isLoaded = false; + m_isUnloaded = false; + m_fileHandle.read("/toy/fig/ty_fig_data.dat", Heaps::ItemResource, 0); + setData(m_fileHandle.getBuffer(), m_fileHandle.getSize()); + m_isLoaded = true; + return true; +} + +bool tyFigListDataManager::isLoadFinish() { + if (!m_isLoaded) { + if (!m_fileHandle.isReady()) { + return false; + } + setData(m_fileHandle.getBuffer(), m_fileHandle.getSize()); + m_isLoaded = true; + return true; + } + return true; +} + +// NONMATCHING +// Can get closer to a match by initializing the pointers to +// "m_bySeries-2" and "m_byKind-2", then adding back the 2 when +// dereferencing, but this would still result in UB +void tyFigListDataManager::setData(void* fileBuf, u32 fileSz) { + utRelocate object(fileBuf, fileSz); + m_data = static_cast(object.getPublicAddress("tyDataList")); + m_count = 0; + while (m_data[m_count].id >= 0) { + m_count++; + } + + u32* bySeries = m_bySeries; + for (u32 i = 0; i < 22; i++) { + for (u32 j = 0; j < m_count; j++) { + if (i == m_data[j].series) { + *bySeries++ = j; + } + } + } + + u32* byKind = m_byKind; + for (u32 i = 23; i < 33; i++) { + for (u32 j = 0; j < m_count; j++) { + if (i == m_data[j].kind) { + *byKind++ = j; + } + } + } + m_isLoaded = true; +} + +u32 tyFigListDataManager::getFigListSeries(s32 series, u32 pageNum, u32* figList) { + u32* lst; + u32 lstSize = 0; + u32 total = 0; + u32 start = pageNum * TrophiesPerPage; + + if (!m_isLoaded) { + return 0; + } + + lst = figList; + for (u32 i = 0; i < m_count && lstSize < TrophiesPerPage; i++) { + tyFigListData* fig = m_data + i; + if (series == fig->series && gmCheckExistFigure(fig->id) == true && ++total > start) { + *lst++ = i; + lstSize++; + } + } + return lstSize; +} + +/** + * Get the number of pages of existing trophies belonging + * to the specified series + */ +u32 tyFigListDataManager::getPageNumSeries(s32 series) { + u32 n = 0; + if (!m_isLoaded) { + return 0; + } + + for (u32 i = 0; i < m_count; i++) { + tyFigListData* fig = m_data + i; + if (series == fig->series && gmCheckExistFigure(fig->id) == true) { + n++; + } + } + + return (n % TrophiesPerPage == 0) ? n / TrophiesPerPage : n / TrophiesPerPage + 1; +} + +/** + * Given a trophy ID, return the ID of the next acquired trophy that would appear + * in the "By Series" ordering + */ +u32 tyFigListDataManager::nextIdSeries(u32 id) { + if (!m_isLoaded) { + return 0; + } + + u32 next; + for (next = 0; next < m_count; next++) { + if (id == m_bySeries[next]) { + if (++next >= m_count) { + next = 0; + } + break; + } + } + + u32 start = next; + for (u32 i = 0; i < m_count; i++) { + tyFigListData* fig = m_data; + u32 j = (start + i) % m_count; + if (gmCheckExistFigure(fig[m_bySeries[j]].id) == true) { + return m_bySeries[j]; + } + } + + return id; +} + +u32 tyFigListDataManager::prevIdSeries(u32 id) { + if (!m_isLoaded) { + return 0; + } + + s32 prev; + for (prev = 0; prev < m_count; prev++) { + if (id == m_bySeries[prev]) { + if (--prev < 0) { + prev = m_count - 1; + } + break; + } + } + + for (u32 i = 0; i < m_count; i++) { + u32 j = m_count - (i - prev); + if (prev >= i) { + j = prev - i; + } + if (gmCheckExistFigure(m_data[m_bySeries[j]].id) == true) { + return m_bySeries[j]; + } + } + + return id; +} + +u32 tyFigListDataManager::getFigListKind(s32 kind, u32 pageNum, u32* figList) { + u32* lst; + u32 lstSize = 0; + u32 total = 0; + u32 start = pageNum * TrophiesPerPage; + + if (!m_isLoaded) { + return 0; + } + + lst = figList; + for (u32 i = 0; i < m_count && lstSize < TrophiesPerPage; i++) { + tyFigListData* fig = m_data + i; + if (kind == fig->kind && gmCheckExistFigure(fig->id) == true && ++total > start) { + *lst++ = i; + lstSize++; + } + } + return lstSize; +} + +/** + * Get the number of pages of existing trophies belonging + * to the specified kind. + */ +u32 tyFigListDataManager::getPageNumKind(s32 kind) { + u32 n = 0; + + if (!m_isLoaded) { + return 0; + } + for (u32 i = 0; i < m_count; i++) { + tyFigListData* fig = m_data + i; + if (kind == fig->kind && gmCheckExistFigure(fig->id) == true) { + n++; + } + } + + return (n % TrophiesPerPage == 0) ? n / TrophiesPerPage : n / TrophiesPerPage + 1; +} + +u32 tyFigListDataManager::nextIdKind(u32 id) { + if (!m_isLoaded) { + return 0; + } + + u32 next; + for (next = 0; next < m_count; next++) { + if (id == m_byKind[next]) { + if (++next >= m_count) { + next = 0; + } + break; + } + } + + for (u32 i = 0; i < m_count; i++) { + u32 j = (next + i) % m_count; + if (gmCheckExistFigure(m_data[m_byKind[j]].id) == true) { + return m_byKind[j]; + } + } + + return id; +} + +u32 tyFigListDataManager::prevIdKind(u32 id) { + if (!m_isLoaded) { + return 0; + } + + s32 prev; + for (prev = 0; prev < m_count; prev++) { + if (id == m_byKind[prev]) { + if (--prev < 0) { + prev = m_count - 1; + } + break; + } + } + + for (u32 i = 0; i < m_count; i++) { + u32 j = m_count - (i - prev); + if (prev >= i) { + j = prev - i; + } + if (gmCheckExistFigure(m_data[m_byKind[j]].id) == true) { + return m_byKind[j]; + } + } + + return id; +} + +/** + * Get the total number of collected trophies that come before id in + * the ordering specified in 'orderBySeries' (if false, order by kind) + */ +u32 tyFigListDataManager::getTotalId(u32 id, bool orderBySeries) { + if (!m_isLoaded) { + return 0; + } + + if (orderBySeries) { + u32 total = 0; + for (u32 i = 0; i < m_count; i++) { + if (gmCheckExistFigure(m_data[m_bySeries[i]].id) == true) { + total++; + if (id == m_bySeries[i]) { + return total; + } + } + } + } else { + u32 total = 0; + for (u32 i = 0; i < m_count; i++) { + if (gmCheckExistFigure(m_data[m_byKind[i]].id) == true) { + total++; + if (id == m_byKind[i]) { + return total; + } + } + } + } + return id; +} + +s32 tyFigListDataManager::getBilTexFileIdx(u32 i) { + if (!m_isLoaded) { + return -1; + } + return m_data[i].bilTexIdx / 10; +} + +s32 tyFigListDataManager::getBilTexFileIdxFigId(u16 id) { + if (!m_isLoaded) { + return -1; + } + tyFigListData* fig = getFigDataId(id); + return (!fig) ? -1 : fig->bilTexIdx / 10; +} + +void tyFigListDataManager::getBilTexFileNameFigId(u16 id, char* name) { + sprintf(name, "/toy/figdisp/figdisp%03d.brres", getBilTexFileIdxFigId(id)*10); +} + +void tyFigListDataManager::getBilTexName(u32 i, char* name) { + sprintf(name, "MenCollDisply01.%03d", m_data[i].bilTexIdx); +} + +void tyFigListDataManager::getBilTexNameFigId(u32 id, char* name) { + sprintf(name, "MenCollDisply01.%03d", getFigDataId(id)->bilTexIdx); +} + +tyFigListData* tyFigListDataManager::getFigDataId(u32 id) { + if (!m_isLoaded) { + return 0; + } + + for (u32 i = 0; i < m_count; i++) { + if (id == m_data[i].id) { + return &m_data[i]; + } + } + return 0; +}