ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flipper Zero Tama P1 模拟器实战

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。做法只有两步在 microSD 卡根目录新建tama_p1文件夹把从网络找到的 P1 ROM 改名为rom.bin放进去。文件缺失时应用会显示 No ROM模拟 CPU 异常停机则显示 Halted后面排查时会用到这两个提示。一键编译并启动把tama_p1文件夹复制进 Flipper 固件源码树的applications/plugins/tama_p1然后一条命令完成编译、安装并启动./fbt launch_app APPSRCapplications/plugins/tama_p1应用元信息在 application.fam 中EXTERNAL 类型编译成 .fap 插件、入口函数tama_p1_app、依赖 gui 与 storage 两个系统服务、1 KB 堆栈发布到 Games_Extra 分类。三键操作与隐藏功能Flipper 按键对应动作左键宠物 A 键OK 键宠物 B 键右键宠物 C 键上键静音模拟同时按 AC下键短按立即存档返回短按立即存档返回长按存档并退出上键静音、下键存档是文档没细说但源码里已实现的功能全部映射逻辑集中在 tama_p1.c 的输入回调中。它是怎么做到的4 位内核TamaLIB 与 ROM 字节序重排要解决的问题Tamagotchi P1 的大脑是一颗 Epson E0C6S46 4 位 MCU而网上流传的 ROM 来自芯片裸片照片的光学识读。tamalib/ 把取指、标志位、定时器、中断全部软件化用一张内存表复刻整颗芯片的地址空间区域地址大小半字节RAM0x000–0x27F640显示区 10xE00–0xE4F80显示区 20xE80–0xECF80I/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 里APPSRCapplications\plugins\tama_p1是 Windows 写法Linux 或 macOS 的 Shell 要换成正斜杠。⚠️编译报未使用参数TamaLIB 的cpu.c、hw.c会触发-Wunused-parameter严格告警配置下可能直接编译失败需要在固件site_cons/cc.scons的CCFLAGS里加-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 为TamaP1与TamaLIB。配合 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),仅供参考
返回列表