news 2026/9/20 17:19:11

Flipper Zero Tama P1 模拟器实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flipper Zero Tama P1 模拟器实战

Flipper Zero Tama P1 模拟器实战

【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper

一只住进 Flipper Zero 的虚拟宠物

把 Tamagotchi P1 的 ROM 拷进 SD 卡,启动 Tama P1 模拟器,Flipper Zero 的屏幕上就会出现一只黑白像素的拓麻歌子:它会按蜂鸣器叫、用 8 个状态图标提示饥饿与游戏,退出前存档,下次启动它还会从上次的状态继续长大。

这个项目位于 Applications/Official/source-OLDER/xMasterX/tama_p1 目录,是典型的"外部插件 + 跨平台模拟内核"结构:应用外壳负责 ROM 加载、事件循环和渲染,真正干活的是 TamaLIB——一个从零实现的、硬件无关的 4 位机模拟库。读完整篇文章,你既能把它跑起来,也看得懂一台 32,768 Hz 的 4 位 CPU 是怎么被"装进" Flipper 的。

最短路径:放 ROM、编译、启动

放置 ROM 文件

ROM 路径在 tama.h 里写死为/ext/tama_p1/rom.bin。做法只有两步:

  1. 在 microSD 卡根目录新建tama_p1文件夹;
  2. 把从网络找到的 P1 ROM 改名为rom.bin放进去。

文件缺失时应用会显示 "No ROM",模拟 CPU 异常停机则显示 "Halted",后面排查时会用到这两个提示。

一键编译并启动

tama_p1文件夹复制进 Flipper 固件源码树的applications/plugins/tama_p1,然后一条命令完成编译、安装并启动:

./fbt launch_app APPSRC=applications/plugins/tama_p1

应用元信息在 application.fam 中:EXTERNAL 类型(编译成 .fap 插件)、入口函数tama_p1_app、依赖 gui 与 storage 两个系统服务、1 KB 堆栈,发布到 Games_Extra 分类。

三键操作与隐藏功能

Flipper 按键对应动作
左键宠物 A 键
OK 键宠物 B 键
右键宠物 C 键
上键静音(模拟同时按 A+C)
下键(短按)立即存档
返回(短按)立即存档
返回(长按)存档并退出

上键静音、下键存档是文档没细说但源码里已实现的功能,全部映射逻辑集中在 tama_p1.c 的输入回调中。

它是怎么做到的

4 位内核:TamaLIB 与 ROM 字节序重排

要解决的问题:Tamagotchi P1 的"大脑"是一颗 Epson E0C6S46 4 位 MCU,而网上流传的 ROM 来自芯片裸片照片的光学识读。tamalib/ 把取指、标志位、定时器、中断全部软件化,用一张内存表复刻整颗芯片的地址空间:

区域地址大小(半字节)
RAM0x000–0x27F640
显示区 10xE00–0xE4F80
显示区 20xE80–0xECF80
I/O 寄存器0xF00–0xF7F128

取舍在内存占用上:Flipper 的 STM32WB 内存宝贵,TamaLIB 默认开启LOW_FOOTPRINT宏,把无效地址段裁掉、每两个半字节打包进一个字节,整张表只占 464 字节,读写靠位运算宏完成。

ROM 还有个字节序问题:文件里的 4 位字和 TamaLIB 预期的位置正好相反,加载后必须重排:

for(size_t i = 0; i < fi.size; i += 2) { uint8_t b = ctx->rom[i]; ctx->rom[i] = ctx->rom[i + 1]; ctx->rom[i + 1] = b & 0xF; }

之后tamalib_init以 64000 作为时间基准启动内核,节拍从此对齐到 64 kHz。

HAL 适配:时钟、屏幕与蜂鸣器

TamaLIB 从不直接碰硬件,只依赖一个hal_t函数表;Flipper 侧的实现全在 hal.c,不到两百行。关键取舍有三处:

时钟get_timestamp()直接读 STM32 定时器 TIM2 的计数器,预分频设为 999,计数频率恰好 64 kHz,与内核基准一致:

LL_TIM_InitTypeDef tim_init = { .Prescaler = 999, .CounterMode = LL_TIM_COUNTERMODE_UP, .Autoreload = 0xFFFFFFFF, };

屏幕:模拟器的 32×16 像素不直接上屏,而是写进uint32_t framebuffer[16]——每行一个 32 位整数,1 位对应 1 个像素;8 个状态图标写进一个icons位图。真正的绘制交给 GUI 线程,所以 HAL 里的update_screen()是空函数。

蜂鸣器:TamaLIB 上报的频率要先除以 10 才是真实频率,play_frequency再调furi_hal_speaker_start驱动内置喇叭。

双线程时间模型与存档流水线

模拟和绘制各走一个线程,中间用一把递归互斥锁加 8 深度消息队列隔开。模拟线程在 worker 里循环调用tamalib_step();GUI 线程由 30 FPS 的周期定时器驱动重绘:

furi_timer_start(timer, furi_kernel_get_tick_frequency() / 30);

节奏控制靠sleep_until():模拟时间还没到目标时间戳时,它释放互斥锁、让出 1 个 tick 的 CPU 再拿回锁继续步进。这样模拟线程既不会空转耗资源,也不会把 64 kHz 节拍拖慢。重绘回调则在同一把锁下读帧缓冲,按 2 倍缩放居中画出 64×32 的画面,再按位图把 14×14 的图标排在矩阵上下两侧。

存档走同一条流水线。save.bin/ext/tama_p1/save.bin,约 850 字节)的布局:4 字节魔数"TLST"加版本号,随后是 PC 与 X/Y/A/B 等寄存器、两个定时器时间戳和可编程定时器参数、16 个中断槽,最后是整块 RAM 与 I/O。加载时先校验魔数与版本,失败只打日志不恢复;成功后调tamalib_refresh_hw()让显示与蜂鸣器状态重新同步。长按返回退出、下键短按、返回短按都会触发一次完整写档,宠物不会因为你合上设备就"死"了。

踩坑与排查

  • ⚠️文档说"无存档"?README 前文写着进度会重置,但同一文档的 Implemented 一节和源码都表明存档已实现。以源码为准,前文属于过时描述。
  • ⚠️fbt 命令的反斜杠:README 里APPSRC=applications\plugins\tama_p1是 Windows 写法,Linux 或 macOS 的 Shell 要换成正斜杠。
  • ⚠️编译报未使用参数:TamaLIB 的cpu.chw.c会触发-Wunused-parameter,严格告警配置下可能直接编译失败,需要在固件site_cons/cc.sconsCCFLAGS里加-Wno-unused-parameter抑制。
  • ⚠️"No ROM" 与 "Halted":前者是rom.bin路径或文件名不对;后者是模拟 CPU 停机,多半是 ROM 内容不对,换一份再试。
  • 图标编译:应用引用compiled/assets_icons.h。仓库里已带好编译产物,若替换了icons/下的 PNG,需要用固件根目录的scripts/assets.py重新生成这个头文件。
  • 串口定位:源码用FURI_LOG_D/E打了 ROM 加载、存档读写和按键序列日志(Tag 为TamaP1TamaLIB)。配合 FlipperScripts 里的serial_logger.py监听串口,即可确认按键映射与状态机行为。

边界与延伸

当前版本的能力边界(来自 README 的 To-do 与源码注释):

  • 单一存档槽位,没有多存档;
  • 无法在游戏内重置宠物,只能删掉save.bin重来;
  • 未实现测试模式与音量调节;
  • 加速未实现——源码里fast_forward_done被直接置为 true。

想继续深入,建议从 tamalib 的cpu.c取指与标志位处理读起,再对照hw.c里的定时器与中断模型;之后可以翻看 Applications 目录下的其他游戏类插件,体会同一套"HAL + 模拟内核"模式如何复用到别的芯片上。

【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper

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

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

Docker部署iVentoy:轻松搭建PXE网络批量装机平台

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

作者头像 李华
网站建设 2026/9/20 17:16:26

从迷宫基线到多智能体电梯群控:深度强化学习调度实现

简介&#xff1a;面向计算机相关专业学生与开发者&#xff0c;这份资源围绕深度强化学习在多智能体电梯群控系统中的应用展开&#xff0c;重点实现目的楼层预约调度算法&#xff0c;适合作为毕设、课设或项目立项演示。包内共30个文件&#xff0c;包含13个Python源码、14个编译…

作者头像 李华
网站建设 2026/9/20 17:13:36

开源AI知识管理工具:团队经验自动传承的瑞士军刀

一个人离职&#xff0c;带着三年的踩坑记录走了&#xff1b;新人刚来&#xff0c;同一批问题在团队里被反复问了一遍又一遍。这个场景我相信每个团队都经历过&#xff0c;但真正把它解决掉的产品没几个。腾讯开源的那个 AI 管理项目第一次打动我的&#xff0c;不是它又接了多少…

作者头像 李华
网站建设 2026/9/20 17:12:14

Atlas 300V 24G部署YOLO实战:从模型转换到推理调优

1. 从“atlas”这个词说起&#xff1a;它到底指什么第一次看到“atlas”这个项目标题&#xff0c;很多人脑子里会蹦出好几个完全不同的东西。做地图的会想到那本地图集&#xff0c;做后端的会想到MongoDB那个托管数据库服务&#xff0c;做AI推理的则会立刻反应过来——这是昇腾…

作者头像 李华
网站建设 2026/9/20 17:11:07

基于知识图谱的个性化学习资源推荐系统设计与实践

简介&#xff1a;一套基于知识图谱的个性化学习资源推荐系统设计与实现资料包&#xff0c;面向需要完成毕业设计、课程项目或研究该方向的学生与开发者。系统围绕知识点图谱构建、学习者建模、混合推荐算法及模块化实现展开&#xff0c;包含数据收集、图谱构建、用户模型管理、…

作者头像 李华