From c4db2660e281f27aeabfffbad9d10835b587d3a3 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Fri, 22 May 2026 21:26:23 -0700 Subject: [PATCH] archive: support official LZMA SDK 16.04 APIs The bundled 7z reader used older SDK field names directly. Keep the existing Windows SDK layout as the default path, and add an opt-in UAE_7Z_SDK_1604 path for the public 16.04 headers. Select the matching XZ finish constant by SDK family so the shared archive code can build with either header set. --- include/zarchive.h | 1 - zfile.cpp | 5 +++- zfile_archive.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) diff --git a/include/zarchive.h b/include/zarchive.h index 9edb8921..0812a9e1 100644 --- a/include/zarchive.h +++ b/include/zarchive.h @@ -123,7 +123,6 @@ extern struct zvolume *archive_directory_lha(struct zfile *zf); extern struct zfile *archive_access_lha (struct znode *zn); extern struct zvolume *archive_directory_zip(struct zfile *zf); extern struct zvolume *archive_directory_7z (struct zfile *z); -extern struct zfile *archive_access_7z (struct znode *zn); extern struct zvolume *archive_directory_rar (struct zfile *z); extern struct zfile *archive_access_rar (struct znode *zn); extern struct zvolume *archive_directory_lzx (struct zfile *in_file); diff --git a/zfile.cpp b/zfile.cpp index 3cd9b80b..a293987c 100644 --- a/zfile.cpp +++ b/zfile.cpp @@ -1160,7 +1160,10 @@ static struct zfile *wrp (struct zfile *z, int *retcode) #ifdef A_7Z #include "7z/Xz.h" -#include "7z/Lzmadec.h" +#include "7z/LzmaDec.h" +#ifdef UAE_7Z_SDK_1604 +#define LZMA_FINISH_ANY CODER_FINISH_ANY +#endif #include "7z/7zCrc.h" static void *SzAlloc (void *p, size_t size) diff --git a/zfile_archive.cpp b/zfile_archive.cpp index f85c3a99..4c158770 100644 --- a/zfile_archive.cpp +++ b/zfile_archive.cpp @@ -510,6 +510,7 @@ static struct zfile *archive_unpack_zip (struct zfile *zf) #include "7z/7z.h" #include "7z/Alloc.h" +#include "7z/7zBuf.h" #include "7z/7zFile.h" #include "7z/7zVersion.h" #include "7z/7zCrc.h" @@ -573,6 +574,51 @@ static void init_7z (void) _tzset (); } +#ifdef UAE_7Z_SDK_1604 +static TCHAR *sevenzip_get_name(const CSzArEx *db, UInt32 index) +{ + size_t len = SzArEx_GetFileNameUtf16(db, index, NULL); + UInt16 *src = xcalloc(UInt16, len > 0 ? len : 1); + TCHAR *out; + + SzArEx_GetFileNameUtf16(db, index, src); +#if defined(UNICODE) || defined(_UNICODE) + out = xmalloc(TCHAR, len > 0 ? len : 1); + for (size_t i = 0; i < len; i++) + out[i] = (TCHAR)src[i]; + if (!len) + out[0] = 0; +#else + out = xmalloc(TCHAR, len * 4 + 1); + size_t o = 0; + for (size_t i = 0; i < len && src[i]; i++) { + uae_u32 c = src[i]; + if (c >= 0xd800 && c <= 0xdbff && i + 1 < len && src[i + 1] >= 0xdc00 && src[i + 1] <= 0xdfff) { + c = 0x10000 + ((c - 0xd800) << 10) + (src[++i] - 0xdc00); + } + if (c < 0x80) { + out[o++] = (TCHAR)c; + } else if (c < 0x800) { + out[o++] = (TCHAR)(0xc0 | (c >> 6)); + out[o++] = (TCHAR)(0x80 | (c & 0x3f)); + } else if (c < 0x10000) { + out[o++] = (TCHAR)(0xe0 | (c >> 12)); + out[o++] = (TCHAR)(0x80 | ((c >> 6) & 0x3f)); + out[o++] = (TCHAR)(0x80 | (c & 0x3f)); + } else { + out[o++] = (TCHAR)(0xf0 | (c >> 18)); + out[o++] = (TCHAR)(0x80 | ((c >> 12) & 0x3f)); + out[o++] = (TCHAR)(0x80 | ((c >> 6) & 0x3f)); + out[o++] = (TCHAR)(0x80 | (c & 0x3f)); + } + } + out[o] = 0; +#endif + xfree(src); + return out; +} +#endif + struct SevenZContext { CSzArEx db; @@ -623,6 +669,33 @@ struct zvolume *archive_directory_7z (struct zfile *z) return NULL; } zv = zvolume_alloc (z, ArchiveFormat7Zip, ctx, NULL); +#ifdef UAE_7Z_SDK_1604 + for (i = 0; i < ctx->db.NumFiles; i++) { + TCHAR *name = sevenzip_get_name(&ctx->db, i); + struct zarchive_info zai; + + memset(&zai, 0, sizeof zai); + zai.name = name; + zai.flags = SzBitWithVals_Check(&ctx->db.Attribs, i) ? ctx->db.Attribs.Vals[i] : -1; + zai.size = SzArEx_GetFileSize(&ctx->db, i); + if (SzBitWithVals_Check(&ctx->db.MTime, i)) { + CNtfsFileTime *mt = ctx->db.MTime.Vals + i; + uae_u64 t = (((uae_u64)mt->High) << 32) | mt->Low; + if (t >= EPOCH_DIFF) { + zai.tv.tv_sec = (t - EPOCH_DIFF) / RATE_DIFF; + zai.tv.tv_sec -= _timezone; + if (_daylight) + zai.tv.tv_sec += 1 * 60 * 60; + } + } + if (!SzArEx_IsDir(&ctx->db, i)) { + struct znode *zn = zvolume_addfile_abs (zv, &zai); + if (zn) + zn->offset = i; + } + xfree(name); + } +#else for (i = 0; i < ctx->db.db.NumFiles; i++) { CSzFileItem *f = ctx->db.db.Files + i; TCHAR *name = (TCHAR*)(ctx->db.FileNames.data + ctx->db.FileNameOffsets[i] * 2); @@ -647,6 +720,7 @@ struct zvolume *archive_directory_7z (struct zfile *z) zn->offset = i; } } +#endif zv->method = ArchiveFormat7Zip; return zv; } -- 2.47.3