diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp index 0a7f992f..2251402d 100644 --- a/src/core/file_format/pkg.cpp +++ b/src/core/file_format/pkg.cpp @@ -189,9 +189,9 @@ bool PKG::Extract(const std::string& filepath, const std::filesystem::path& extr u32 ndinode = 0; int ndinode_counter = 0; bool dinode_reached = false; + bool uroot_reached = false; std::vector compressedData; std::vector decompressedData(0x10000); - extractPaths[2] = extract_path.parent_path() / GetTitleID(); // Get iNdoes and Dirents. for (int i = 0; i < num_blocks; i++) { @@ -226,6 +226,30 @@ bool PKG::Extract(const std::string& filepath, const std::filesystem::path& extr } } + // let's deal with the root/uroot enteries here. + // Sometimes it's more than 2 enteries (Tomb Raider Remastered) + const std::string_view flat_path_table(&decompressedData[0x10], 15); + if (flat_path_table == "flat_path_table") { + uroot_reached = true; + } + + if (uroot_reached) { + for (int i = 0; i < 0x10000; i += ent_size) { + Dirent dirent; + std::memcpy(&dirent, &decompressedData[i], sizeof(dirent)); + ent_size = dirent.entsize; + if (dirent.ino != 0) { + ndinode_counter++; + } else { + // Set the the folder according to the current inode. + // Can be 2 or more (rarely) + extractPaths[ndinode_counter] = extract_path.parent_path() / GetTitleID(); + uroot_reached = false; + break; + } + } + } + const char dot = decompressedData[0x10]; const std::string_view dotdot(&decompressedData[0x28], 2); if (dot == '.' && dotdot == "..") { @@ -261,7 +285,7 @@ bool PKG::Extract(const std::string& filepath, const std::filesystem::path& extr std::filesystem::create_directory(extractPaths[table.inode]); } ndinode_counter++; - if ((ndinode_counter + 3) == ndinode) // 3 for root, uroot and flat_path_table. + if ((ndinode_counter + 1) == ndinode) // 1 for the image itself (root). end_reached = true; } } diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index e9bd92b0..3750bf35 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -255,7 +255,8 @@ void GameListFrame::RequestGameMenu(const QPoint& pos) { for (const auto& pair : psf.map_integers) { QTableWidgetItem* keyItem = new QTableWidgetItem(QString::fromStdString(pair.first)); - QTableWidgetItem* valueItem = new QTableWidgetItem(QString::number(pair.second)); + QTableWidgetItem* valueItem = + new QTableWidgetItem(QString("0x").append(QString::number(pair.second, 16))); tableWidget->setItem(row, 0, keyItem); tableWidget->setItem(row, 1, valueItem); @@ -483,10 +484,9 @@ void GameListFrame::Refresh(const bool from_drive, const bool scroll_after) { game.pic_path = picpath.toStdString(); game.name = psf.GetString("TITLE"); game.serial = psf.GetString("TITLE_ID"); - game.fw = (QString("%1").arg(psf.GetInteger("SYSTEM_VER"), 8, 16, QLatin1Char('0'))) - .mid(1, 3) - .insert(1, '.') - .toStdString(); + u32 fw_int = psf.GetInteger("SYSTEM_VER"); + QString fw = QString::number(fw_int, 16).toUpper().left(3).insert(1, '.'); + game.fw = (fw_int == 0) ? "0.00" : fw.toStdString(); game.version = psf.GetString("APP_VER"); game.category = psf.GetString("CATEGORY"); @@ -812,7 +812,7 @@ void GameListFrame::SetListMode(const bool& is_list) { m_gui_settings->SetValue(gui::game_list_listMode, is_list); - Refresh(true); + Refresh(false); m_central_widget->setCurrentWidget(m_is_list_layout ? m_game_list : m_game_grid); } diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 49063435..c7f78795 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -116,7 +116,7 @@ void MainWindow::CreateConnects() { m_gui_settings->SetValue(gui::main_window_gamelist_visible, checked); }); connect(ui->refreshGameListAct, &QAction::triggered, this, - [this] { m_game_list_frame->Refresh(true); }); + [this] { m_game_list_frame->Refresh(false); }); connect(m_icon_size_act_group, &QActionGroup::triggered, this, [this](QAction* act) { static const int index_small = gui::get_Index(gui::game_list_icon_size_small);