# nes_sim **Repository Path**: pangxiongfei/nes_sim ## Basic Information - **Project Name**: nes_sim - **Description**: c语言版本nes游戏模拟器,基于lvgl9.5 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-08 - **Last Updated**: 2026-09-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NES 游戏模拟器 用纯 C 写的 FC / NES 模拟器,界面基于 LVGL 9.5,能在 PC(SDL2 仿真)和 ARM Linux 板子(Framebuffer / DRM)上跑。 6502 CPU、PPU、APU 都是完整实现,支持 33 种 Mapper、5 种卡带容器格式。 作者:pangxiongfei(452457010@qq.com) 仓库:https://gitee.com/pangxiongfei/nes_sim ## 简介 从硬件时序模拟到图形菜单,整个链路都在工程里: - **模拟器核心**:6502 + PPU + APU + 卡带,纯 C,不依赖任何 UI / 音频后端,可以单独抽出来复用。 - **集成层**:把模拟器输出的 256x240 RGB565 帧缓冲缩放后刷到屏幕,键盘 / 手柄映射成 NES 手柄信号,APU 混音后送声卡。 - **界面**:LVGL 9.5 做的 ROM 选择菜单,中文 ROM 名用 FreeType 渲染(阿里巴巴普惠体),扫到什么文件就显示什么,不需要中文名映射表。 模拟器内核基于 [DIJI-NES-2](https://github.com/JohnnyonFlame/diji-ne2) 实现,在其上补了卡带容器抽象、Mapper 自动注册、LVGL 集成层和多显示后端。 ## 目录结构 ``` . ├── build.sh # 构建 / 运行入口 ├── tools/ │ └── toolchain/ # aarch64 交叉工具链分卷包,构建时自动解压 └── source/ # 源码树(CMake 顶层在此) ├── Makefile # 转发给 cmake(含工具链解压) ├── CMakeLists.txt # 顶层:目标架构、工具链、子目录 ├── cmake/ # 工具链文件 + lvgl 实例辅助 │ ├── toolchain_aarch64.cmake │ ├── toolchain_x86_64.cmake │ └── lvgl_instance.cmake # 给本应用单独编一份 lvgl(target 名 lvgl_nes) ├── external/ # 第三方库,configure 阶段自动编译 │ ├── CMakeLists.txt # zlib -> freetype -> alsa_lib │ ├── lvgl/ # LVGL 9.5 │ ├── freetype/ zlib/ alsa/ └── nes_game/ # 应用源码 ├── main.c # 集成层:菜单、状态机、显示、音频、输入 ├── lv_conf.h # 本应用专属 LVGL 配置 ├── nes_init.ld # 链接脚本(Mapper / 格式自动注册段) ├── log_file.c # 日志落盘与轮转 ├── roms/ # 内置 ROM ├── assets/ # 中文字体 ├── common/include/ # 收编的公共头(日志宏、配置、通用类型) └── nes/ # 模拟器核心 ├── cpu6502.c ppu.c apu.c cartridge.c nes.c ├── cart/mapper/ # 33 种 Mapper,NES_MAPPER_EXPORT 自动注册 └── cart/format/ # iNES / NES2.0 / UNIF / FDS / NSF ``` 跑起来之后:`nes_clock()` 按 262 条扫描线推进一帧(VBlank 触发 NMI,MMC3 IRQ 负责卷轴切换), 一帧约 29780 个 CPU 周期;画面写进帧缓冲后由集成层缩放 blit 到 LVGL canvas, 最后 `lv_timer_handler()` 呈现。音频是独立线程按声卡消费速率驱动的,和渲染主循环分开,卡顿不会爆音。 ## 编译 ```bash ./build.sh x86 # 本地编译,SDL2 仿真,PC 上开发调试用 ./build.sh fb # ARM64 交叉编译,Framebuffer,旧版树莓派 ./build.sh drm # ARM64 交叉编译,DRM/KMS,树莓派 5 ./build.sh clean # 清空 output/ ``` x86 下要先装 SDL2: ```bash sudo apt-get install -y build-essential cmake pkg-config libsdl2-dev ccache ``` freetype / zlib / alsa-lib 不用装,构建时由 `external/` 自动编进工程 sysroot。 首次编译要编这几个第三方库,x86 几分钟,交叉编译更久;之后有 ccache,重编很快。 ## 运行 ```bash ./build.sh run # 直接跑 nes,进 ROM 菜单 ./build.sh run roms/xxx.nes # 单 ROM 直跑,返回即退出 ``` 产物在 `output/install/bin/`(`nes` + `roms/` + 字体)。x86 直接弹窗口,板子上要 `sudo`(drm 需要 root 访问 `/dev/dri/*`)。 按键: - 菜单:`↑` `↓` 选择,`PageUp` / `PageDown` 翻页,`Enter` 开始 - 游戏:方向键 = 十字键,`Z` = A,`X` = B,`Enter` = Start,`Shift` = Select - `Esc` 回 ROM 菜单(单 ROM 直跑时就是退出),`Ctrl+C` 退出程序 板子上由 evdev 线程读 `/dev/input/eventX`,映射同上。 ## 调试 ```bash ./build.sh x86 -v # 回显编译命令 ./build.sh x86 -d # bash -x 跟踪脚本 gdb ./output/install/bin/nes ``` 常见问题: - 板子黑屏:看 `/dev/fb0` 或 `/dev/dri/*` 在不在(drm 要 root) - 触摸没反应:`evtest /dev/input/eventX` 确认设备节点(默认 `/dev/input/event0`) - 找不到 ROM:确认运行目录下有 `roms/` 目录(放置 `.nes` 文件) ## 加点东西 新增 Mapper:在 `source/nes_game/nes/cart/mapper/` 加一个 `mapperNN.c`,实现操作集后用 `NES_MAPPER_EXPORT(ops)` 注册。链接脚本会把注册项收进 `.nes_mappers` 段,`mapper.c` 自动发现, `cartridge.c` 和 CMakeLists 都不用动。 新增卡带格式:在 `nes/cart/format/` 加 `xxx.c`,用 `NES_FORMAT_EXPORT(ops)` 注册,`format.c` 同样自动发现。 ## 其它 LVGL 为什么要单独编一份:官方 CMake 把 target 名写死成 `lvgl`,而 `lv_conf.h` 会改变 LVGL 内部结构体的布局 (色深、内存大小这些),库和使用它的应用必须同源同配置。所以这里用 `cmake/lvgl_instance.cmake` 另起一个 target 名 `lvgl_nes`,单独编译并通过 `LV_CONF_PATH` 注入本应用的 `lv_conf.h`。 提交代码前跑一遍 `./build.sh x86`,确认没有新增警告(应用源码开了 `-Wall -Wextra`)。 有问题或建议联系 pangxiongfei:452457010@qq.com 参考或者用到的开源仓库: - [DIJI-NES-2](https://github.com/JohnnyonFlame/diji-ne2) 模拟器内核 - [FCEUX](https://github.com/TASEmulators/fceux) 部分 Mapper 与 NSF 解析的参考实现 - [LVGL](https://github.com/lvgl/lvgl) 9.5 - [FreeType](https://www.freetype.org/) 中文渲染 - [zlib](https://zlib.net/) FreeType 的依赖 - [ALSA](https://www.alsa-project.org/) 板子音频 - [SDL2](https://www.libsdl.org/) x86 窗口 / 音频 / 输入 - [阿里巴巴普惠体](https://www.alibabafonts.com/) 界面字体,免费商用 - [NESdev Wiki](https://www.nesdev.org/wiki/Nesdev_Wiki) 硬件和 Mapper 资料 第三方库各自遵循其原始许可证,内核遵循 DIJI-NES-2 的上游许可。 ROM 版权归各自权利人,仓库里自带的 ROM 只用于技术演示和兼容性验证。