news 2026/9/14 8:41:28

PCSX2 内置的 Zycore-C:一套支撑 Zydis 反汇编引擎的跨平台 C 基础库深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PCSX2 内置的 Zycore-C:一套支撑 Zydis 反汇编引擎的跨平台 C 基础库深度解析

PCSX2 内置的 Zycore-C:一套支撑 Zydis 反汇编引擎的跨平台 C 基础库深度解析

【免费下载链接】pcsx2PCSX2 - The Playstation 2 Emulator项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2

导读

Zycore(Zyan Core Library for C)是一套以平台无关为核心目标的 C 语言基础库:它为上层代码统一提供整型/布尔类型、编译器与平台与架构检测宏、断言与工具宏、位集(Bitset)、字符串(String)以及 Vector/List 等容器类型,并提供了面向无 LibC 环境的函数回退实现。在 PCSX2 仓库中,Zycore 以 Zydis 反汇编器内嵌依赖的形式存在(源码位于 3rdparty/zydis/dependencies/zycore,并被 3rdparty/zydis/CMakeLists.txt 直接编译进 zydis 库),是调试器与动态重编译器(如 pcsx2/x86/ix86-32/iR5900.cpp)正确解析 x86/x86-64 指令的前提。读完本文,你将掌握 Zycore 的类型体系、宏机制、容器设计与无 LibC 回退策略,并能看懂 PCSX2 中 Zydis/Zycore 相关代码的底层原理。

一、Zycore 在 PCSX2 中的定位

Zycore 在官方 README 中的自我定位是:

Internal library providing platform independent types, macros and a fallback for environments without LibC.

(面向内部使用的库,提供平台无关的类型、宏,以及针对无 LibC 环境的回退方案。)

它不是独立对外发布的工具库,而是为 Zydis(x86/x86-64 反汇编器)这类底层解析引擎提供"地基"的支撑库。在 PCSX2 中,它的落点非常具体:

  • 3rdparty/zydis/CMakeLists.txt 把dependencies/zycore/src/下的Allocator.cArgParse.cBitset.cFormat.cList.cString.cVector.cZycore.c以及API/下的Memory.cProcess.cSynchronization.cTerminal.cThread.c全部直接编译进zydis静态库,并把dependencies/zycore/include/Zycore/*.h作为公开头文件暴露;
  • PCSX2 的 x86 重编译器/调试器代码通过#include "Zydis/Zydis.h"间接引入 Zycore 的头文件(见 pcsx2/x86/ix86-32/iR5900.cpp)。例如该文件中自定义的反汇编 Formatter 回调直接使用ZYAN_CHECK(...)ZyanStatus等 Zycore 提供的宏与类型来拼接符号与绝对地址输出。

也就是说,Zycore 表面上"隐身",但 PCSX2 的指令反汇编、绝对地址计算、符号格式化等调试能力,都依赖这套基础类型与宏体系才能跨 MSVC/GCC/Clang 正确编译运行。

二、平台无关类型体系(Types.h)

Zycore 的全部类型定义集中在 include/Zycore/Types.h 中,其设计原则是:无论底层是标准 LibC、还是完全没有 LibC 的裸机环境,上层代码看到的类型签名永远一致

2.1 整型家族

类型含义备注
ZyanU8/ZyanU16/ZyanU32/ZyanU64无符号整型宽度固定,与uint8_t等对齐
ZyanI8/ZyanI16/ZyanI32/ZyanI64有符号整型宽度固定
ZyanUSize/ZyanISize与指针等宽的尺寸/差值类型等价于size_t/ptrdiff_t
ZyanUPointer/ZyanIPointer指针相关整型等价于uintptr_t/intptr_t

类型映射分两条路径实现(Types.h):

  • 有 LibC 时:直接#include <stdint.h>/<stddef.h>,将uint8_tsize_tuintptr_t等一一 typedef 为Zyan*类型,保证与标准库完全一致;
  • 无 LibC 时(ZYAN_NO_LIBC:MSVC/ICC 路径使用unsigned __int8等编译器内建类型,GNU 路径优先使用__UINT8_TYPE____UINT64_TYPE____SIZE_TYPE__等编译器预定义宏,仅在缺少这些宏时才回退到unsigned char等基础 C 类型。对于ZyanU64,在__x86_64__且非__ILP32__时使用unsigned long int,否则使用unsigned long long int

这套路径还顺带定义了与stdint.h平行的极值宏(ZYAN_INT8_MINZYAN_UINT32_MAXZYAN_UINT64_MAX等),确保无 LibC 环境下也能写出可移植的边界判断。

有趣的是,Types.h 用ZYAN_STATIC_ASSERT在编译期硬性校验所有类型的大小与符号性假设,例如sizeof(ZyanU64) == 8sizeof(ZyanUPointer) == sizeof(void*),任何平台上类型宽度不符都会直接编译失败,从根源上杜绝"移植了但类型错了"的隐患。

2.2 逻辑类型与指针

  • ZyanBool:底层就是ZyanU80视为假、非 0 视为真,配合ZYAN_FALSE (0u)ZYAN_TRUE (1u)使用;
  • ZyanTernaryZyanI8实现的三态类型,取值为ZYAN_TERNARY_FALSE (-1)ZYAN_TERNARY_UNKNOWN (0)ZYAN_TERNARY_TRUE (1),用于表达"未知"这种既非真也非假的中间状态;
  • ZyanVoidPointer/ZyanConstVoidPointervoid*/const void*的别名;
  • ZYAN_NULL:定义为((void*)0)
  • ZyanCharPointer/ZyanConstCharPointer:C 风格(NUL 结尾)字符串指针。

三、宏体系:检测、断言与工具(Defines.h)

include/Zycore/Defines.h 是 Zycore 的"元编程中枢",它让同一份 C 代码可以在 MSVC、GCC、Clang、Intel ICC 下获得一致的宏接口。

3.1 编译器 / 平台 / 架构三级检测

三级检测逐层递进,全部基于预定义宏,优先级与语义如下(Defines.h):

  • 编译器ZYAN_CLANGZYAN_GCCZYAN_ICCZYAN_MSVCZYAN_BORLAND,其中 Clang 同时定义ZYAN_GNUC以获得 GCC 兼容行为,且 Clang-cl 还会额外定义ZYAN_CLANG_CLZYAN_MSVC
  • 平台ZYAN_WINDOWSZYAN_EMSCRIPTENZYAN_WASIZYAN_APPLEZYAN_LINUXZYAN_FREEBSDZYAN_NETBSDZYAN_SOLARISZYAN_HAIKUZYAN_UNIX,其中所有类 Unix 平台会统一追加ZYAN_POSIX
  • 架构ZYAN_X64ZYAN_X86ZYAN_AARCH64ZYAN_ARMZYAN_WASMZYAN_LOONGARCHZYAN_PPC64ZYAN_PPCZYAN_RISCV64,无法识别时直接#error "Unsupported architecture detected"强制终止编译;
  • 内核/用户态:检测到_KERNEL_MODEKERNEL__KERNEL__等时定义ZYAN_KERNEL,否则定义ZYAN_USER
  • 调试/发布:MSVC/Borland 依据_DEBUG,GCC/ICC/Clang 依据NDEBUG,分别定义ZYAN_DEBUGZYAN_RELEASE

3.2 断言与调试宏

  • ZYAN_ASSERT(condition):运行时断言。无 LibC 时退化为(void)(condition)空操作;Windows 内核模式映射到NT_ASSERT;其余情况映射到标准assert
  • ZYAN_STATIC_ASSERT(x):编译期断言,按标准依次尝试 C11_Static_assert、C++11static_assert,最终退化为"用typedef声明一个长度依赖条件真假(1 或 -1)的数组"这一经典技巧,失败即编译错误(Defines.h);
  • ZYAN_UNREACHABLE:按平台/编译器映射到__builtin_unreachable()__assume(0)__fastfail(0){ assert(0); abort(); },向编译器声明"代码路径不可达"。

3.3 常用工具宏

作用
ZYAN_MACRO_CONCAT(x, y)/ZYAN_MACRO_CONCAT_EXPAND(x, y)##拼接标识符;EXPAND 版先展开参数再拼接
ZYAN_UNUSED(x)消除"未使用参数"告警
ZYAN_FALLTHROUGH标注 switch 中有意穿透的分支
ZYAN_BITFIELD(x)声明位域的: x语法包装
ZYAN_ARRAY_LENGTH(a)sizeof(a)/sizeof((a)[0])求数组元素个数
ZYAN_MIN/ZYAN_MAX/ZYAN_ABS极值与绝对值
ZYAN_IS_POWER_OF_2(x)判断 2 的幂(注意x == 0恒真)
ZYAN_IS_ALIGNED_TO(x, align)/ZYAN_ALIGN_UP/ZYAN_ALIGN_DOWN对齐判断与向上/向下取整(仅支持 2 的幂对齐)
ZYAN_NEEDS_BIT(n, b)/ZYAN_BITS_TO_REPRESENT(n)判断"表示 n 是否需要第 b 位"、计算表示 n 所需的最少位数
ZYAN_DIV64(n, divisor)Linux 内核态映射到内核的do_div,否则普通除法

此外还有一批编译器属性宏:ZYAN_DEPRECATEDZYAN_DLLEXPORT/ZYAN_DLLIMPORTZYAN_INLINEZYAN_NOINLINEZYAN_NO_SANITIZE(what)ZYAN_PRINTF_ATTR/ZYAN_WPRINTF_ATTR(printf 风格格式化函数检查)等。

3.4 符号导出与版本控制

  • ZYCORE_EXPORT/ZYCORE_NO_EXPORT:静态构建(ZYCORE_STATIC_BUILD)时为空宏;共享库构建时依据ZYCORE_SHOULD_EXPORT映射到__declspec(dllexport/dllimport)或 GCC 的__attribute__((visibility(...)))。Defines.h 中还保留了旧宏名ZYCORE_STATIC_DEFINEZycore_EXPORTS的兼容转换并打印改名警告(Defines.h);
  • ZYCORE_VERSION是 64 位版本号常量,配合 include/Zycore/Zycore.h 中的ZYCORE_VERSION_MAJOR/MINOR/PATCH/BUILD四个宏可按位拆分出主/次/补丁/构建号;ZycoreGetVersion()在运行时返回该值。

四、LibC 抽象与无 LibC 回退(LibC.h)

include/Zycore/LibC.h 是 README 中标注为 "WiP(进行中)" 的部分,但它的设计已经非常清晰:

  • 未定义ZYAN_NO_LIBC时,直接把标准库函数/类型逐一定义为ZYAN_*别名:ZYAN_MALLOCmallocZYAN_FREEfreeZYAN_MEMCPYmemcpyZYAN_STRLENstrlenZYAN_VSNPRINTFvsnprintf,以及ZyanVAListva_listZyanFileFILEZYAN_STDIN/STDOUT/STDERR等;
  • 定义ZYAN_NO_LIBC时,则提供一组内联实现作为"最后防线"。作者在注释中明确承认这些实现"完全不追求性能优化,任何标准库实现都能轻松胜过它们",其目的是"为没有可用 libc 的环境提供兜底"。这部分目前覆盖了全部string.h类函数(ZYAN_MEMCHRZYAN_MEMCMPZYAN_MEMCPYZYAN_MEMMOVE(正确处理源/目标重叠)、ZYAN_MEMSETZYAN_STRCATZYAN_STRCHRZYAN_STRCMPZYAN_STRCPYZYAN_STRLENZYAN_STRTOKZYAN_STRSTR等),而malloc/freevsnprintf的兜底实现目前仍是注释占位(无法在无内存管理器的环境里凭空实现);
  • 开发者也可以定义ZYAN_CUSTOM_LIBC,自行提供整套替换函数,绕过内置路径。

五、容器类型:Vector、List、Bitset 与 String

Zycore 把最常见的容器以"结构体 + 操作函数"的 C 风格实现出来,这也是 README 中列出的重点能力。

5.1 ZyanVector:动态数组

include/Zycore/Vector.h 定义的ZyanVector结构包含:内存分配器指针、增长因子(growth_factor)、收缩阈值(shrink_threshold)、当前元素数(size)、容量(capacity)、单元素字节数(element_size)、元素析构回调(destructor)与数据指针。它提供三类关键行为:

  • 容量策略常量:最小容量为ZYAN_VECTOR_MIN_CAPACITY (1),默认增长因子为 2(成倍扩容),默认收缩阈值为 4(元素数降到容量的 1/4 时收缩),见 Vector.h;
  • 构造方式:支持栈上静态初始化与基于分配器的动态初始化(ZyanVectorInit/ZyanVectorInitCustomBuffer等),以及ZyanVectorDestroy释放;
  • 操作接口ZyanVectorPushBackZyanVectorPopBackZyanVectorGetZyanVectorSetZyanVectorInsertZyanVectorDeleteZyanVectorResizeZyanVectorClearZyanVectorReserve等,构成完整的动态数组语义。

5.2 ZyanList:链表

include/Zycore/List.h 提供双向链表实现,支持头插/尾插/中间插入、按节点遍历(ZyanListNode)、节点析构回调以及整表销毁,适用于需要频繁插入删除、不要求随机访问的场景。

5.3 ZyanBitset:位集

include/Zycore/Bitset.h 实现的ZyanBitset结构非常简洁——一个size字段记录位集大小,内部数据则直接内嵌一个ZyanVectorZyanVector bits),即"用动态数组承载位数据"。它提供的核心能力包括:

  • 按位读写:ZyanBitsetSetZyanBitsetGetZyanBitsetFlip
  • 批量清零/置位:ZyanBitsetClearZyanBitsetSetAll
  • 集合运算:ZyanBitsetANDZyanBitsetORZyanBitsetXOR,这些运算通过函数指针类型ZyanBitsetByteOperation(对两个字节执行操作的回调)逐字节作用于两个位集,见 Bitset.h;
  • 枚举已置位索引:ZyanBitsetEnumeratorInit+ZyanBitsetEnumeratorNext,支持高效遍历所有为 1 的位。

5.4 ZyanString / ZyanStringView:字符串

include/Zycore/String.h 提供两类字符串抽象:

  • ZyanString:拥有缓冲区的动态字符串(内嵌ZyanVector管理字符数据),支持ZyanStringInitZyanStringAppendZyanStringInsertZyanStringReplaceZyanStringToLowerCase/UpperCase以及格式化为子串视图等操作;
  • ZyanStringView:只读视图,仅指向已有字符串的一段区间,不拥有数据,适合作为函数参数避免拷贝。

六、配套设施:分配器、状态码与原子操作

除 README 列出的能力外,Zycore 还提供了一批支撑性模块,共同构成完整的基础设施:

  • 分配器抽象(include/Zycore/Allocator.h):ZyanAllocatormalloc/calloc/realloc/free包装成可替换的分配器接口,容器可通过它实现自定义内存管理;
  • 状态码体系(include/Zycore/Status.h):ZyanStatus是 32 位状态码,ZYAN_MAKE_STATUS(error, module, code)把"是否错误(1 位) + 模块 ID(11 位) + 具体错误码(20 位)"打包成单一值;ZYAN_SUCCESS/ZYAN_FAILED用于判断成败,ZYAN_CHECK(status)则是在失败时直接return状态码的"快速失败"惯用法。模块 ID 已预定义ZYAN_MODULE_ZYCOREZYAN_MODULE_ARGPARSE等。PCSX2 中 Zydis 的 Formatter 回调就大量使用ZYAN_CHECK链式传播错误;
  • 原子操作(include/Zycore/Atomic.h 及其Internal/AtomicGNU.hAtomicMSVC.h):分别基于 GCC 内建原子与 MSVC 的Interlocked*函数族提供跨平台原子读写/加减;
  • OS API 封装(include/Zycore/API/):Memory.hProcess.hSynchronization.hTerminal.hThread.h将内存映射、进程、同步原语、终端 IO、线程等系统能力统一封装,Windows 走 Win32 API、POSIX 平台走 pthread/mmap 等;
  • 命令行解析(include/Zycore/ArgParse.h):提供参数解析器;格式化(include/Zycore/Format.h)提供格式化输出能力;对象操作(include/Zycore/Object.h)与比较器(include/Zycore/Comparison.h)则为容器提供元素析构回调与比较回调的通用定义。

七、编译集成方式与使用前提

Zycore 不是一个需要单独安装的系统库,而是作为 Zydis 的源码依赖直接参与构建:

  • 在 PCSX2 中,zycore 的全部.c.h被 3rdparty/zydis/CMakeLists.txt 显式列为zydis库的源文件与头文件,与 Zydis 自身的src/Decoder.csrc/Formatter*.c等编译进同一目标,最终由 PCSX2 的 CMake 体系(参见根目录 CMakeLists.txt)链接进模拟器;
  • 使用方只需#include <Zycore/Zycore.h>(主入口,包含类型定义并声明ZycoreGetVersion)或按需引入Zycore/Types.hZycore/Vector.h等细分头文件;
  • 由于 zycore 的所有头文件都带有完善的extern "C"保护(如 Zycore.h),C++ 项目(如 PCSX2 的重编译器与调试器代码)可以直接包含而不必担心名字修饰问题;
  • 需要无 LibC 环境时,编译期定义ZYAN_NO_LIBC即可切换到内建回退实现;如需完全自定义替换函数,则定义ZYAN_CUSTOM_LIBC并提供自己的实现。

八、源码阅读路线图

如果希望深入理解 Zycore 的每个模块,可以沿以下路径在仓库内继续探索(全部路径相对于仓库根目录):

  1. include/Zycore/Types.h:类型体系 + 编译期大小/符号性校验;
  2. include/Zycore/Defines.h:检测宏、断言、工具宏、导出宏;
  3. include/Zycore/LibC.h:LibC 别名与无 LibC 内联回退实现;
  4. include/Zycore/Vector.h、include/Zycore/List.h、include/Zycore/Bitset.h、include/Zycore/String.h:四类容器/字符串;
  5. include/Zycore/Status.h、include/Zycore/Allocator.h、include/Zycore/Atomic.h:状态码、分配器、原子操作;
  6. 落地示例:pcsx2/x86/ix86-32/iR5900.cpp 中 Zydis Formatter 回调对ZyanStatusZYAN_CHECK的调用,可以直观看到这些基础设施在生产代码中的真实用法。

结语

Zycore 的定位决定了它的价值不在于功能花哨,而在于稳定与可移植:从整型宽度、布尔语义到编译器/平台/架构检测,再到无 LibC 环境下的内联回退,它把"写一次、处处编译"这件事做到了 C 语言能实现的极致。在 PCSX2 中,正是这套基础库支撑着 Zydis 反汇编器在多编译器、多平台下稳定工作,从而为模拟器的调试与动态重编译功能提供了可靠底座。

【免费下载链接】pcsx2PCSX2 - The Playstation 2 Emulator项目地址: https://gitcode.com/GitHub_Trending/pc/pcsx2

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 8:40:42

AIGC检测与降率工具:原理、应用与行业解决方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 8:39:43

实测三款省Token工具:CodeGraph、AOCI与Understand Anything对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 8:37:47

基于OpenClaw的广告营销Agent基础设施实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 8:34:24

无人船路径规划与靠泊控制的NLP技术应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华