树莓派GPIO与RetroPie打造可插拔实体卡带N64模拟器
1. 项目概述当数字模拟遇见实体交互作为一个折腾过不少复古游戏方案的玩家我一直觉得纯粹的软件模拟少了点“灵魂”。那种从卡槽里拔出《塞尔达传说时之笛》吹一吹金手指再插上《超级马里奥64》的仪式感是任何游戏列表下拉菜单都无法替代的。所以当我看到有人用树莓派和3D打印技术把实体卡带交互重新带回到模拟器上时立刻就被这个点子击中了。这不仅仅是一个游戏机更像是一个连接数字与物理世界的桥梁项目。这个项目的核心目标很明确用树莓派和RetroPie系统打造一台外观复古、内核现代的N64游戏机并且让它支持真正的、可插拔的物理卡带。每一张卡带插入时都能自动加载并启动对应的游戏完美复刻了当年换卡即玩的体验。实现这一魔法的主要功臣是树莓派那排可编程的GPIO引脚、几个微动开关以及一点点3D建模和Python脚本的功夫。它解决了模拟器设备交互单一的问题为复古游戏爱好者和硬件DIYer提供了一个兼具怀旧情怀与技术挑战的绝佳实践。无论你是想给自己做一个独一无二的游戏终端还是想学习如何用树莓派的GPIO控制外部世界这个项目都再合适不过。你需要准备的除了基础的焊接和建模知识更多的是一份对老游戏和动手创造的热情。接下来我会把我从零开始复现并优化这个项目的完整过程、踩过的坑以及一些能让体验更上一层楼的技巧毫无保留地分享出来。2. 核心思路与硬件选型解析2.1 为什么是树莓派与RetroPie选择树莓派作为硬件核心几乎是复古游戏模拟领域的“标准答案”但这背后有坚实的逻辑支撑。首先性能与功耗的平衡是关键。以树莓派4B为例其四核Cortex-A72处理器和VideoCore VI显卡足以流畅模拟N64、PS1及更早世代的主机。而它的功耗通常仅在3W到7W之间这意味着你可以使用一个普通的手机充电宝为其供电极大地提升了便携性。其次丰富的GPIO接口是这个项目的灵魂。40个可编程的引脚让我们可以轻松地连接按钮、传感器等外部设备实现卡带检测这种定制化功能这是普通电视盒子或迷你PC所不具备的。RetroPie系统则是软件层面的不二之选。它本质上是一个基于Raspbian现为Raspberry Pi OS的Linux发行版但预装了EmulationStation前端、RetroArch核心以及大量经过优化的模拟器“libretro cores”。它的优势在于高度集成与社区驱动。你不需要手动编译安装各个模拟器RetroPie提供了一个图形化的管理界面可以方便地配置手柄、管理游戏库、调整模拟器参数。更重要的是其庞大的社区意味着任何你遇到的问题几乎都能找到解决方案或现成的脚本。对于这个项目我们需要的是一台能稳定运行N64模拟器的树莓派。实测下来树莓派3B是入门门槛可以运行大部分N64游戏但部分复杂3D游戏如《完美黑暗》可能存在帧数不足。树莓派4B2GB或4GB内存版是更推荐的选择它能提供更稳定的帧率和更好的兼容性。至于更新的树莓派5性能固然更强但考虑到功耗和散热设计需要更复杂的处理对于N64模拟而言属于“性能过剩”树莓派4B是性价比与体验的甜点。2.2 “可工作卡带”的物理逻辑设计这是整个项目最具巧思的部分。如何让一块塑料卡带告诉树莓派“该运行哪个游戏”原作者的方案简洁而优雅利用卡带内部不同的物理结构触发不同的按钮组合。具体来说我们在3D打印的游戏机外壳的卡带插槽内部左右两侧各安装一个微动开关按钮。每个开关连接树莓派的一个GPIO引脚。然后我们制作三张不同的卡带卡带A只在左侧有凸起。插入时仅按下左侧按钮对应GPIO 17。卡带B只在右侧有凸起。插入时仅按下右侧按钮对应GPIO 18。卡带C左右两侧都有凸起。插入时同时按下两个按钮GPIO 17 18。这样三张卡带就产生了三种不同的电信号状态。我们的Python脚本持续监听这两个GPIO引脚的电平。当检测到特定的按下组合时就执行对应的命令行指令启动指定的游戏ROM。这个方案避免了使用昂贵的RFID或磁簧管等传感器成本极低且可靠性非常高完美还原了“插入即玩”的物理体验。注意微动开关的选择有讲究。应选择行程短、触发力度轻的型号。因为卡带是靠插入的推力来触发开关如果开关需要很大力度才能按下会导致插拔卡带手感生涩甚至损坏卡带或开关。我推荐使用常见的6x6mm贴片微动开关其高度和触发力度都比较合适。2.3 物料清单与工具准备以下是完成本项目所需的全部物料和工具。你可以根据实际情况进行替代但核心部件不建议更改。类别物品规格/说明可选/替代方案核心硬件树莓派主板推荐树莓派4B (2GB/4GB)树莓派3B性能稍弱Micro SD卡Class 10或以上容量≥32GB用于安装系统和游戏USB闪存盘容量≥8GB用于向树莓派传输游戏ROMUSB游戏手柄推荐Xbox/PS4样式兼容RetroPie蓝牙手柄亦可但需额外配置电源适配器树莓派4B需5V/3A Type-C电源供电不足会导致系统不稳定交互部件微动开关6x6mm贴片式2个也可用轻触开关但需注意安装方式GPIO连接线母对公杜邦线4条用于连接开关与树莓派GPIO引脚电阻10kΩ 电阻2个用于GPIO引脚的上拉电阻可选代码中可启用内部上拉外壳与结构3D打印机FDM类型打印精度尚可即可如果无打印机可考虑使用现成盒子改造PLA/ABS耗材颜色自选约需200-300克PETG材料强度更高更适合经常插拔的卡带螺丝与螺母M2.5或M3规格若干用于固定树莓派主板和微动开关软件与工具电脑Windows/Mac/Linux均可用于烧录系统、建模和传输文件SD卡烧录工具BalenaEtcher推荐或Raspberry Pi Imager3D建模软件Fusion 360免费个人版、Tinkercad在线简易或Blender螺丝刀、电烙铁、剥线钳等基础工具3. 软件环境搭建与游戏资源导入3.1 RetroPie系统安装与初始配置第一步是让树莓派“活”起来并变成一个游戏机。首先访问RetroPie的官方网站下载与你的树莓派型号对应的镜像文件。切记选择正确的版本树莓派4B的镜像与3B的不通用。下载完成后使用BalenaEtcher进行烧录。这是一个非常直观的工具选择镜像文件、选择SD卡驱动器、点击“Flash”即可。整个过程大约需要5-10分钟。烧录完成后将SD卡插入树莓派连接HDMI线、USB手柄和电源。首次启动会进行文件系统扩展和基础包安装等待其自动完成。进入EmulationStation主界面后首先需要配置手柄。按照屏幕提示依次按下手柄上的各个按键进行映射。这里有个关键技巧建议将某个不常用的按键如Select或某个肩键映射为“热键”Hotkey。这个热键组合如HotkeyStart用于快速退出游戏、呼出 RetroArch 菜单等至关重要。接下来配置网络。在EmulationStation主界面按Start键进入主菜单选择“WiFi”或“有线网络”进行连接。联网后建议通过“RetroPie Setup”菜单更新系统。进入主菜单的“Configuration / tools” - “retropie-setup”选择“Update all installed packages”来获取最新的模拟器核心和系统更新。这能解决很多潜在的兼容性问题。3.2 游戏ROM的获取与规范存放RetroPie本身不提供任何游戏ROM你需要自行准备。请务必确保你拥有的ROM文件是来自于你合法拥有的游戏卡带备份遵守当地版权法律。获得ROM文件后如何将它们放入树莓派最方便的方法是使用U盘。将U盘格式化为FAT32或exFAT格式然后插入已启动的树莓派。等待约30秒后拔出此时U盘上会自动生成一个名为retropie的文件夹。将U盘插回电脑你会发现retropie文件夹下有一个roms目录里面按游戏机平台分好了子文件夹。对于N64游戏你需要将.n64或.z64格式的ROM文件放入roms/n64文件夹内。ROM的命名最好使用英文且不要包含特殊字符和空格这能避免很多模拟器识别问题。例如“Super Mario 64.n64”可以重命名为“Super_Mario_64.n64”或“SuperMario64.n64”。传输完成后将U盘安全弹出再插回树莓派。系统会自动将游戏拷贝到SD卡中并在界面上显示出来。实操心得除了U盘你还可以通过SFTP如FileZilla直接通过网络传输ROM。在电脑的文件管理器地址栏输入sftp://retropie.local或树莓派的IP地址用户名pi密码raspberry即可访问/home/pi/RetroPie/roms目录直接上传。这种方法更适合批量管理或后续添加单个游戏。3.3 N64模拟器核心的选择与优化RetroPie为N64提供了多个模拟器核心不同的核心对游戏的兼容性和性能表现差异巨大。进入游戏列表在任意N64游戏上按“选择键”Select选择“游戏设置”即可更改模拟器核心。lr-mupen64plus-next这是目前最推荐、兼容性最好的核心。它基于Mupen64Plus并整合了多种图形插件Rice、GlideN64。对于绝大多数游戏它都能提供可玩的速度和较好的图形效果。首次运行某游戏时它可能会提示你下载所需的“纹理”同意即可这能提升部分游戏的画面。lr-parallel-n64另一个选择在某些游戏上可能略有性能优势但整体兼容性稍逊于前者。Mupen64Plus (Standalone)独立版模拟器配置选项更丰富但通常需要通过命令行或配置文件调整对新手不友好。选定核心后还可以进行一些关键优化以提升体验。在游戏中按“热键X”可以呼出RetroArch快速菜单。这里有几个重要设置分辨率在“设置”-“视频”中可以尝试将分辨率设置为“640x480”或“720x480”。降低分辨率是提升帧率最有效的方法。帧率同步关闭“设置”-“视频”中的“垂直同步”VSync有时能减少输入延迟但可能引起画面撕裂。着色器谨慎使用。虽然CRT扫描线着色器能增加复古感但会显著消耗性能在N64游戏上可能导致卡顿。最重要的建议是逐个游戏测试并保存核心选项。在RetroArch快速菜单中选择“覆盖层”-“保存游戏覆盖层”。这样每个游戏的模拟器核心和专属设置都会被单独记住互不干扰。4. 外壳与卡带的3D设计与打印实战4.1 外壳建模的功能性考量设计外壳不仅是让它看起来像N64更要确保所有功能组件都能严丝合缝地安装和工作。我使用Fusion 360进行设计你也可以使用Tinkercad等更简单的工具。首先你需要精确测量树莓派主板和所有端口的位置。重点关注的区域包括USB与以太网端口侧这是手柄连接的主要区域开口必须准确且预留足够的插入空间。HDMI与电源端口侧确保电源线能牢固插入HDMI线不会过度弯折。GPIO排针上方必须预留足够高的空间以便杜邦线能够顺利连接。Micro SD卡槽最好设计一个可开合的小盖板方便日后更换SD卡而不是将整个外壳拆开。对于卡带插槽的设计这是精髓所在。插槽的内部宽度和高度需要与你设计的卡带完美匹配既要保证卡带能顺畅插入拔出又不能有太大的晃动。在插槽内部的左右两侧需要设计两个用于安装微动开关的立柱或卡槽。开关的按钮应正好朝向插槽中心确保卡带上的凸起能准确按压到它。开关的背部也需要有结构固定防止其被按歪。散热设计不容忽视。树莓派4B在运行N64模拟时会产生一定热量。在外壳的顶部和底部需要设计足够的通风栅格。更进阶的做法是在主板CPU位置的正上方设计一个风扇安装位使用5V小风扇从外壳外部吸风或向内部吹风。4.2 卡带设计的精妙之处卡带的设计目标只有一个以特定的物理结构触发特定的开关组合。每张卡带的主体部分尺寸应与插槽内径保持约0.2-0.3mm的间隙这是FDM 3D打印的典型公差。关键在于卡带前端内部的“触发凸起”。你需要设计三种变体左侧凸起卡带在卡带内部左侧设计一个长方体凸起其位置和高度要确保当卡带完全插入时这个凸起能压下左侧的微动开关而右侧空间是空的。右侧凸起卡带与上相反只有右侧有凸起。双侧凸起卡带左右两侧都有凸起。为了增加真实感和防止插反你可以在卡带外壳上建模出N64卡带经典的防呆口并在主机插槽对应位置做出凸起。同时可以在卡带表面用浮雕或贴纸的方式写上游戏名称和logo。打印与后处理建议打印外壳和卡带时建议使用0.15mm或0.2mm的层高以提高表面质量。对于经常摩擦的卡带插槽内壁和卡带本身可以尝试增加外壳层数例如3-4层来增强耐磨性。打印完成后务必用锉刀和砂纸仔细打磨插槽内部和卡带的边角确保没有任何毛刺阻碍插拔。组装前最好先进行“干测试”——不接线仅测试卡带能否顺畅插入并准确压到开关位置。4.3 内部布局与组装工艺打印好的外壳通常由底盖和面盖两部分组成。组装顺序至关重要固定树莓派使用塑料支柱和螺丝将树莓派主板固定在底盖的对应位置上。确保所有端口都对准了外壳的开孔。焊接与布线这是需要耐心的一步。将两个微动开关的引脚焊上导线。每个开关有三只脚公共端COM、常开端NO、常闭端NC。我们使用常开端和公共端。将两个开关的公共端或其中一个取决于接线方式用导线并联然后连接到树莓派的任意一个GND接地引脚例如Pin 6。将左侧开关的常开端通过杜邦线连接到GPIO 17Pin 11右侧开关连接到GPIO 18Pin 12。安装开关将焊接好线的微动开关小心地安装到外壳插槽内部预设的位置。可以使用一点点热熔胶或强力双面胶辅助固定但要注意不要影响按钮的按压行程。理线与测试将GPIO连接线整理好用扎带或胶布固定避免其干扰风扇如果安装了的话或卡在盖板间。先不要合上面盖通电开机用镊子短接开关的引脚测试Python脚本是否能正确响应后续会写脚本。确认无误后再进行最终组装。最终封装合上面盖用螺丝锁紧。一张充满个性的贴纸或喷漆能让你的DIY主机完成最后的“灵魂注入”。5. GPIO编程与卡带检测逻辑实现5.1 Python脚本的编写与原理剖析让硬件“活”起来的核心是一段运行在后台的Python脚本。它利用RPi.GPIO库持续监听两个引脚的状态并根据状态变化执行相应的命令。我们先来看一个增强版的脚本它更健壮并解决了原方案中的一些潜在问题。#!/usr/bin/env python3 N64 Cartridge Reader Script for RetroPie Listens to GPIO 17 18 for cartridge insertion events. import RPi.GPIO as GPIO import time import os import subprocess from pathlib import Path # 用户配置区域 # 定义GPIO引脚使用BCM编号 PIN_BTN_LEFT 17 # 对应左侧开关 PIN_BTN_RIGHT 18 # 对应右侧开关 # 定义卡带触发后的延迟时间秒防止误触发 DEBOUNCE_TIME 0.3 # 定义每个卡带对应的游戏启动命令 # 格式[模拟器核心, ROM文件完整路径] GAME_MAPPINGS { left: [lr-mupen64plus-next, /home/pi/RetroPie/roms/n64/Super_Mario_64.n64], right: [lr-mupen64plus-next, /home/pi/RetroPie/roms/n64/The_Legend_of_Zelda.n64], both: [lr-mupen64plus-next, /home/pi/RetroPie/roms/n64/GoldenEye_007.n64], } # 配置结束 def launch_game(core, rom_path): 使用RetroPie的runcommand来启动游戏 # 检查ROM文件是否存在 if not Path(rom_path).is_file(): print(f错误未找到ROM文件 - {rom_path}) return # 构建启动命令 cmd [ /opt/retropie/supplementary/runcommand/runcommand.sh, 0, # 运行模式 _SYS_, # 使用系统默认配置这里我们指定核心 core, rom_path ] print(f正在启动游戏: {rom_path} 使用核心: {core}) try: # 使用subprocess调用避免阻塞主线程 subprocess.Popen(cmd) except Exception as e: print(f启动游戏失败: {e}) def main(): # 设置GPIO模式为BCM GPIO.setmode(GPIO.BCM) # 设置引脚为输入模式并启用内部上拉电阻引脚默认高电平 GPIO.setup(PIN_BTN_LEFT, GPIO.IN, pull_up_downGPIO.PUD_UP) GPIO.setup(PIN_BTN_RIGHT, GPIO.IN, pull_up_downGPIO.PUD_UP) print(N64卡带检测服务已启动...) print(等待卡带插入...) print(左卡带 - 马里奥64 | 右卡带 - 塞尔达 | 双卡带 - 黄金眼) left_state_last GPIO.input(PIN_BTN_LEFT) right_state_last GPIO.input(PIN_BTN_RIGHT) try: while True: left_state_current GPIO.input(PIN_BTN_LEFT) right_state_current GPIO.input(PIN_BTN_RIGHT) # 检测状态变化从高电平未按下变为低电平按下 left_pressed (left_state_last GPIO.HIGH and left_state_current GPIO.LOW) right_pressed (right_state_last GPIO.HIGH and right_state_current GPIO.LOW) if left_pressed and not right_pressed: print(检测到左侧卡带插入) time.sleep(DEBOUNCE_TIME) # 防抖延迟 launch_game(*GAME_MAPPINGS[left]) elif right_pressed and not left_pressed: print(检测到右侧卡带插入) time.sleep(DEBOUNCE_TIME) launch_game(*GAME_MAPPINGS[right]) elif left_pressed and right_pressed: print(检测到双侧卡带插入) time.sleep(DEBOUNCE_TIME) launch_game(*GAME_MAPPINGS[both]) # 更新上一次的状态 left_state_last left_state_current right_state_last right_state_current time.sleep(0.05) # 主循环短暂休眠降低CPU占用 except KeyboardInterrupt: print(\n服务被用户中断。) finally: GPIO.cleanup() print(GPIO资源已清理。) if __name__ __main__: main()脚本原理解析上拉电阻与电平逻辑GPIO.PUD_UP启用了内部上拉电阻。这意味着当开关未按下时引脚通过电阻连接到3.3V高电平当开关按下引脚短接到GND变为低电平。我们检测的就是这个从高到低的“下降沿”。状态检测逻辑脚本不是简单地检查当前是否为低电平而是比较上一次循环和当前循环的状态。只有当状态从高变低时才判定为一次有效的“按下”动作。这避免了卡带一直插着导致游戏被反复启动。防抖处理机械开关在接触瞬间会产生细微的弹跳导致电平快速抖动。DEBOUNCE_TIME变量和time.sleep(DEBOUNCE_TIME)语句就是为了在检测到动作后等待一小段时间让信号稳定再执行后续操作。游戏启动使用subprocess.Popen来调用RetroPie的runcommand.sh脚本启动游戏。Popen会启动新进程而不阻塞当前Python脚本这样服务可以继续监听卡带插拔事件。5.2 将脚本设置为开机自启动服务我们不希望每次开机都要手动去运行这个Python脚本。在Linux下最好的方法是将其配置为一个系统服务。首先将你的脚本例如命名为cartridge_reader.py放到一个合适的位置比如/home/pi/。并赋予其执行权限chmod x /home/pi/cartridge_reader.py然后创建一个服务单元文件sudo nano /etc/systemd/system/cartridge-reader.service在文件中写入以下内容[Unit] DescriptionN64 Cartridge Reader Service Afterretropie.service Wantsnetwork-online.target Afternetwork-online.target [Service] Typesimple Userpi WorkingDirectory/home/pi ExecStart/usr/bin/python3 /home/pi/cartridge_reader.py Restarton-failure RestartSec5 StandardOutputjournal [Install] WantedBymulti-user.target关键参数解释Afterretropie.service确保本服务在RetroPie启动后再运行避免资源冲突。Restarton-failure如果脚本意外崩溃系统会在5秒后自动重启它。Userpi以pi用户身份运行拥有访问ROM目录的权限。保存退出后启用并启动这个服务sudo systemctl daemon-reload sudo systemctl enable cartridge-reader.service sudo systemctl start cartridge-reader.service你可以用以下命令检查服务状态和日志sudo systemctl status cartridge-reader.service journalctl -u cartridge-reader.service -f现在你的树莓派每次开机都会自动运行卡带检测服务。插入卡带听到风扇启动声如果有的话后稍等一秒游戏就应该自动全屏启动了。6. 系统集成、调试与进阶优化6.1 与EmulationStation前端的无缝衔接默认情况下我们的脚本会直接启动游戏绕过EmulationStation的图形界面。这很酷但有时我们可能还是想进入游戏库选择其他游戏。一个更优雅的方案是让卡带触发游戏启动但同时保留手柄操作退出游戏后能回到EmulationStation。这需要我们修改脚本的启动命令并正确配置RetroArch的热键。我们的脚本已经使用了runcommand.sh它会自动处理前端与模拟器之间的切换。当你用卡带启动游戏后想要退出游戏回到前端需要用到之前配置的“热键”。通常是同时按住你设置的热键如Select和Start键。确保你的RetroArch输入配置正确。在RetroPie设置菜单中进入Configuration / tools-retropie-setup然后选择Configuration / tools-emulationstation-Clear/Reset Emulation Station input configuration可以重新配置手柄并确认热键设置。一个进阶技巧是你可以修改脚本让插入特定卡带比如双侧卡带时不启动游戏而是执行一个命令直接退出到EmulationStation前端或者甚至重启系统。只需将GAME_MAPPINGS中对应的命令改为[kodi, ]如果你安装了Kodi或者一个自定义的脚本即可。6.2 故障排查与常见问题解决在制作和运行过程中你肯定会遇到一些问题。下面是一个快速排查指南现象可能原因解决方案插入卡带无反应1. Python服务未运行。2. GPIO接线错误或虚焊。3. 卡带凸起未压到开关。4. 脚本中GPIO引脚编号错误。1. 运行sudo systemctl status cartridge-reader.service检查状态。2. 用万用表通断档检查开关按下时是否导通检查杜邦线是否插牢在树莓派正确的引脚上。3. 不装外壳手动用镊子短接GPIO引脚到GND测试脚本是否响应。4. 核对脚本中的PIN_BTN_LEFT和PIN_BTN_RIGHT是否为实际使用的BCM编号Pin 11GPIO17, Pin12GPIO18。游戏启动失败或报错1. ROM文件路径或名称错误。2. 模拟器核心名称错误。3. ROM文件本身损坏或不兼容。1. 在脚本中打印出完整的命令或在终端手动执行runcommand.sh命令测试。2. 在/opt/retropie/libretrocores/下查看确切的模拟器核心文件名或在RetroPie的游戏设置里查看核心名称。3. 尝试在EmulationStation界面手动启动该ROM看是否正常。卡带识别错误如左卡带启动了右卡带的游戏1. 左右开关接线接反。2. 卡带凸起位置做反了。1. 交换脚本中PIN_BTN_LEFT和PIN_BTN_RIGHT的引脚定义试试。2. 检查3D模型确认卡带A的凸起在左侧卡带B在右侧。系统启动后手柄失灵可能我们的Python服务与EmulationStation的手柄检测服务有轻微冲突。在服务文件(.service)中增加Aftergraphical.target或增加启动延迟在ExecStart前加一行ExecStartPre/bin/sleep 5。脚本报权限错误以root用户运行服务但ROM目录属于pi用户。确保服务单元文件中的Userpi设置正确或者将ROM目录权限改为可读。6.3 扩展思路与进阶玩法基础功能实现后这个项目还有巨大的扩展空间增加更多游戏两个开关只有3种组合左、右、双最多对应3个游戏。你可以通过增加开关数量来指数级增加组合。例如使用3个开关可以有7种独立组合2^3 -1就能对应7个游戏。这需要修改外壳设计、卡带结构和Python脚本的逻辑从判断“哪个被按下”变为判断“二进制编码”。加入状态指示灯利用树莓派剩余的GPIO引脚连接LED。例如插入卡带时LED闪烁启动游戏时LED常亮游戏退出时LED熄灭。这能提供更直观的反馈。实现“拔出卡带暂停游戏”这需要更复杂的逻辑。目前的脚本只在检测到“插入动作”时启动游戏。你可以修改脚本使其在检测到卡带“拔出动作”电平从低变高时向模拟器发送一个信号。这通常需要通过RetroArch的网络控制接口或DBus消息来实现难度较高但非常炫酷。美化与个性化使用更高端的3D打印材料如木纹PLA、金属质感耗材或者对打印件进行打磨、喷漆、旧化处理。为每张卡带设计精美的贴纸或激光雕刻图案。甚至可以在外壳上加装一个小屏幕显示当前插入卡带的游戏封面。这个项目的魅力在于它从一个简单的想法出发融合了硬件、软件、设计和怀旧情感。当你亲手将一张实体卡带插入自己制作的机器并看到熟悉的游戏画面亮起时那种成就感远超单纯下载一个模拟器合集。它不仅是一个玩具更是一个属于你自己的、充满个人印记的数字物理交互作品。