ARM Linux DIY(十二)NES 游戏

news2024/12/30 3:45:30

文章目录

    • 前言
    • 交叉编译工具链使能 C++
    • nes 游戏模拟器移植
    • 游戏手柄调试

前言

很多小伙伴为了不让自己的 V3s 吃灰,进而将其打造成游戏机。
我们 DIY 的板子具备屏幕、扬声器、USB Host(可以接游戏手柄),当然也要凑一凑热闹。

交叉编译工具链使能 C++

怎么突然讲到工具链了?
因为待会 nes 游戏模拟器编译需要用到 C++,所以就先提前讲一下
在这里插入图片描述
这里遇到了一个坑,编译 g++ 时,依赖一些库,这些库是我之前没有使能 g++ 时编的,现在使能 g++ 后需要重新编,不然 g++ 编译有问题,一开始我没发现这个问题,怎么编都有问题。
host-gcc-final-12.3.0/ 就是其中一个依赖,将这个目录手动删除,然后重新编译整个工程,g++ 就编译 OK 了。

nes 游戏模拟器移植

源码:https://github.com/nejidev/arm-NES-linux

step1:
修改交叉编译链

CC=/home/liyongjun/project/board/buildroot/DIY_V3S/host/bin/arm-buildroot-linux-gnueabihf-gcc
CCFLAGS += -I /home/liyongjun/project/board/buildroot/DIY_V3S/staging/usr/include
LDFILGS += -L /home/liyongjun/project/board/buildroot/DIY_V3S/staging/usr/lib

step2:
修改 InfoNES_System_Linux.cpp 文件中的 lcd_fb_display_px 函数 (调整 spi 屏幕的颜色)

static int lcd_fb_display_px(WORD color, int x, int y)
{
#if 0
	unsigned char  *pen8;
	unsigned short *pen16;
	pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
	pen16 = (unsigned short *)pen8;
	*pen16 = color;

	return 0;
#endif
	WORD *pen16;
	unsigned char r, g, b;
	r = ((color >> 10) & 0x1f);
	g = ((color >> 5) & 0x3f);
	b = (color & 0x1f);

	color = r<<11|g<<6|b;
	pen16 = (WORD *)(fb_mem + y*line_width + x*px_width);
	*pen16 = color;
	return 0;
}

step3:
下载游戏合集并解压,然后改名为游戏名为英文
链接:https://pan.baidu.com/s/16hIWwYQQEX9aOBDG1dVa0A
提取码:asdf

step4:
运行

root@v3s-diy:~/nes# ./InfoNES rom/218_hdl.nes 
/dev/joypad dev not found 
/dev/input/js0 dev not found 
fb width:240 height:240 

在这里插入图片描述

游戏手柄调试

插入游戏手柄

root@v3s-diy:~# ls /dev/input/
event0
root@v3s-diy:~# 
[  126.159751] usb 1-1.2: new low-speed USB device number 4 using ehci-platform
[  126.421937] input: USB gamepad as /devices/platform/soc/1c1a000.usb/usb1/1-1/1-1.2/1-1.2:1.0/0003:081F:E401.0002/input/input2
[  126.435728] hid-generic 0003:081F:E401.0002: input: USB HID v1.10 Joystick [USB gamepad] on usb-1c1a000.usb-1.2/input0
root@v3s-diy:~# ls /dev/input/
event0  event1  js0

运行游戏

root@v3s-diy:~/nes# ./InfoNES rom/218_hdl.nes 
/dev/joypad dev not found 
fb width:240 height:240

发现游戏手柄按键没有反应

不过,监听 /dev/input/event1 发现按键是有事件产生的

root@v3s-diy:~/nes# hexdump /dev/input/event1
0000000 c086 0003 fa8b 000e 0004 0004 0003 0009
0000010 c086 0003 fa8b 000e 0001 0122 0001 0000
0000020 c086 0003 fa8b 000e 0000 0000 0000 0000
0000030 c087 0003 0a0b 0002 0004 0004 0003 0009
0000040 c087 0003 0a0b 0002 0001 0122 0000 0000
0000050 c087 0003 0a0b 0002 0000 0000 0000 0000
0000060 c087 0003 c80b 000c 0004 0004 0001 0009
0000070 c087 0003 c80b 000c 0001 0120 0001 0000
0000080 c087 0003 c80b 000c 0000 0000 0000 0000
0000090 c087 0003 19cb 000f 0004 0004 0001 0009
00000a0 c087 0003 19cb 000f 0001 0120 0000 0000
00000b0 c087 0003 19cb 000f 0000 0000 0000 0000
00000c0 c089 0003 114f 0006 0003 0000 00ff 0000
00000d0 c089 0003 114f 0006 0000 0000 0000 0000
00000e0 c089 0003 6309 0008 0003 0000 007f 0000
00000f0 c089 0003 6309 0008 0000 0000 0000 0000

那大概率是游戏手柄按键和模拟器设定不匹配
在获取按键值的地方加点打印,记录按键值

// arm-NES-linux/linux/joypad_input.cpp
static int USBjoypadGet(void)
{
	/**
	 * FC手柄 bit 键位对应关系 真实手柄中有一个定时器,处理 连A  连B 
	 * 0  1   2       3       4    5      6     7
	 * A  B   Select  Start  Up   Down   Left  Right
	 */
	//因为 USB 手柄每次只能读到一位键值 所以要有静态变量保存上一次的值
	static unsigned char joypad = 0;
	struct js_event e;
	if(0 < read (USBjoypad_fd, &e, sizeof(e)))
	{
printf("e.type = 0x%x\t", e.type);
printf("e.value = 0x%x\t", e.value);
printf("e.number = 0x%x\n", e.number);
		if(0x2 == e.type)
		{
			/*
			上:
			value:0x8001 type:0x2 number:0x5
			value:0x0 type:0x2 number:0x5
			*/
			if(0x8001 == e.value && 0x5 == e.number)

然后将各个按键值改正确

static int USBjoypadGet(void)
{
	/**
	 * FC手柄 bit 键位对应关系 真实手柄中有一个定时器,处理 连A  连B 
	 * 0  1   2       3       4    5      6     7
	 * A  B   Select  Start  Up   Down   Left  Right
	 */
	//因为 USB 手柄每次只能读到一位键值 所以要有静态变量保存上一次的值
	static unsigned char joypad = 0;
	struct js_event e;
	if(0 < read (USBjoypad_fd, &e, sizeof(e)))
	{
printf("e.type = 0x%x\t", e.type);
printf("e.value = 0x%x\t", e.value);
printf("e.number = 0x%x\n", e.number);
		if(0x2 == e.type)
		{
			/* 上 */
			if(0x8001 == e.value && 0x1 == e.number)
			{
				joypad |= 1<<4;
			}
			
			/* 下 */
			if(0x7fff == e.value && 0x1 == e.number)
			{
				joypad |= 1<<5;
			}
			//松开
			if(0x0 == e.value && 0x1 == e.number)
			{
				joypad &= ~(1<<4 | 1<<5);
			}
			
			/* 左 */
			if(0x8001 == e.value && 0x0 == e.number)
			{
				joypad |= 1<<6;
			}
			
			/* 右 */
			if(0x7fff == e.value && 0x0 == e.number)
			{
				joypad |= 1<<7;
			}
			//松开
			if(0x0 == e.value && 0x0 == e.number)
			{
				joypad &= ~(1<<6 | 1<<7);
			}
		}

		if(0x1 == e.type)
		{
			/* 选择 */
			if(0x1 == e.value && 0x8 == e.number)
			{
				joypad |= 1<<2;
			}
			if(0x0 == e.value && 0x8 == e.number)
			{
				joypad &= ~(1<<2);
			}
			
			/* 开始 */
			if(0x1 == e.value && 0x9 == e.number)
			{
				joypad |= 1<<3;
			}
			if(0x0 == e.value && 0x9 == e.number)
			{
				joypad &= ~(1<<3);
			}

			/* A */
			if(0x1 == e.value && 0x1 == e.number)
			{
				joypad |= 1<<0;
			}
			if(0x0 == e.value && 0x1 == e.number)
			{
				joypad &= ~(1<<0);
			}

			/* B */
			if(0x1 == e.value && 0x2 == e.number)
			{
				joypad |= 1<<1;
			}
			if(0x0 == e.value && 0x2 == e.number)
			{
				joypad &= ~(1<<1);
			}

			/* X */
			if(0x1 == e.value && 0x0 == e.number)
			{
				joypad |= 1<<0;
			}
			if(0x0 == e.value && 0x0 == e.number)
			{
				joypad &= ~(1<<0);
			}

			/* Y */
		 	if(0x1 == e.value && 0x3 == e.number)
			{
				joypad |= 1<<1;
			}
			if(0x0 == e.value && 0x3 == e.number)
			{
				joypad &= ~(1<<1);
			}
		}
		return joypad;
	}
printf("read failed!!!\n");
	return -1;
}

就可以愉快地玩游戏了
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1017758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBootTest

SpringBootTest注解 --基于SpringBoot2.5.7版本 可以在运行基于Spring Boot的测试的测试类上指定的注释。在常规的Spring TestContext框架之上提供了以下特性: 默认提供SpringBootContextLoader作为ContextLoader&#xff0c;也通过 ContextConfiguration(loader…)来自定义 若…

docker安装zookeeper(单机版)

第一步&#xff1a;拉取镜像 docker pull zookeeper第二步&#xff1a;启动zookeeper docker run -d -e TZ"Asia/Shanghai" -p 2181:2181 -v /home/sunyuhua/docker/zookeeper:/data --name zookeeper --restart always zookeeper

基于改进莱维飞行和混沌映射的粒子群优化BP神经网络预测股票价格研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

1990-2022年上市公司常用控制变量数据(1300+变量)

1990-2022年上市公司常用控制变量数据&#xff08;1300变量&#xff09; 1、时间&#xff1a;1990-2022年 2、指标&#xff1a;共计1391个变量&#xff0c;包括但不限于以下类别&#xff1a;、基本信息&#xff08;性质、行业、地址&#xff09;、股票市场&#xff08;发行、…

阿里云无影云电脑详细介绍_无影优势价格和使用

什么是阿里云无影云电脑&#xff1f;无影云电脑&#xff08;原云桌面&#xff09;是一种快速构建、高效管理桌面办公环境&#xff0c;无影云电脑可用于远程办公、多分支机构、安全OA、短期使用、专业制图等使用场景&#xff0c;阿里云百科分享无影云桌面的详细介绍、租用价格、…

通过指针变量存取一维数组元素

任务描述 本关任务&#xff1a;编写程序用指针变量遍历一个数组。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 1.指向数组元素的指针的运算 2.如何遍历数组。 视频1 指针与一维数组 指向数组元素的指针的运算 指针与整数的加减运算 有数组和指针变量的…

区块链(3):区块链去中心化

1 点对点同步区块链的流程 流程图如下&#xff1a; 流程讲解&#xff1a; &#xff08;1&#xff09;连接节点 &#xff08;2&#xff09;向该节点请求最新区块 &#xff08;3&#xff09;请求到区块以后&#xff0c;根据返回的最新区块前置hash是否和我本身的区块hash相等…

抖音矩阵系统-60+自媒体平台一键发布-短视频获客系统

当老板做企业的&#xff0c;想在抖音上做生意的&#xff0c;一定一定要开通蓝V企业号线索版来做矩阵。看看我每天的线索都是999&#xff0c;客服都接待不过来&#xff0c;现在还有300个客资未分配&#xff0c;抖音都在推了企业员工号的玩法&#xff0c;你还在质疑什么&#xff…

ubuntu 18.04 中 eBPF samples/bpf 编译

1. history 信息 一次成功编译 bpf 后执行 history 得到的信息&#xff1a; yingzhiyingzhi-Host:~/ex/ex_kernel/linux-5.4$ history1 ls2 mkdir ex3 cd ex4 mkdir ex_kernel5 ls /boot/6 sudo apt install linux-source7 ls /usr/src/8 uname -r9 cd ex_kernel/10…

Nginx配置最佳实践

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

双向链表的实现(增删查改)——最好理解的链表

双向链表的实现 一&#xff0c;双向链表的特点二&#xff0c;双向链表的结构三&#xff0c;双向链表的内容实现3.1创建node节点3.2初始化3.3打印3.4插入3.4.1尾插3.4.2头插3.4.3在pos位置上插入 3.5删除3.5.1尾删3.5.2头删3.5.3删除pos位置上的数据 四&#xff0c;调试技巧&…

基于Xml方式Bean的配置-Bean的延时加载

SpringBean的配置详解 Bean的延时加载 当lazy-init设置为true时为延时加载&#xff0c;也就是当Spring容器创建的时候&#xff0c;不会立即创建Bean实例&#xff0c;等待用到时再创建Bean实例并储存到单例池中&#xff0c;后续使用该Bean时直接从单例池中获取即可&#xff0c;…

文心一言 VS 讯飞星火 VS chatgpt (94)-- 算法导论9.2 3题

三、用go语言&#xff0c;给出 RANDOMIZED-SELECT的一个基于循环的版本。 文心一言&#xff1a; 在循环中实现 RANDOMIZED-SELECT 的一个版本可以如下所示。这个版本使用 Go 语言编写&#xff0c;利用随机化来选择一个元素&#xff0c;并在循环中不断地调整选择的元素&#x…

红黑树封装实现map和set

全文目录 map和set红黑树的封装红黑树的迭代器begin() 和 end()operator()operator--() map完整代码set完整代码改造后的红黑树代码 map和set map和set 是STL中的容器&#xff0c;两者底层的实现都是参考文档&#xff1a; map参考文档 set参考文档 两个容器底层都是去重的二叉…

Spring复杂对象的3中创建方法

复杂对象是相对于简单对象可以直接 new 出的对象。这种对象在 Spring 中不可以通过简单对象的创建方式来创建。下面我们将通过实现 FactoryBean 接口、实例工厂、静态工厂三种方法来创建。 FactoryBean 接口 Spring 提供 FactoryBean 接口并且提供了 getObject 方法是为了支持…

【Vue.js】生命周期与基本使用

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》 《springMvc使用》 ⛺️ 生活的理想&#xff0c;为了不断更新自己 ! 目录 ​编辑 1.Vue是什么 2.Vue的特点及优势 3. 使用Vue的详细步骤 3.1.导入 3.2…

Vue3引入滑块验证组件-2分钟搞定

安装 npm install --save vue3-slide-verify登录页面引入 template 下 <template><div class"login"><el-card class"cover" v-if"loginUser.data.user"><slide-verifyref"block"slider-text"向右滑动-&…

实验室预约系统设计与实现

实验室预约系统的设计 摘 要 目前各大学的实验项目日益繁多&#xff0c;如何合理预约实验室&#xff0c;已经成为当今各个大学实验室课程预约的难题。因此&#xff0c;这个实验室预约系统就是研究实验室预约的相关问题。实验室预约系统的设计主要是基于B/S模型&#xff0c;在W…

MySQL--MySQL索引事务

事务的概念 事务指逻辑上的一组操作&#xff0c;组成这组操作的各个单元&#xff0c;要么全部成功&#xff0c;要么全部失败。 在不同的环境中&#xff0c;都可以有事务。对应在数据库中&#xff0c;就是数据库事务。 使用 &#xff08;1&#xff09;开启事务&#xff1a;start…

VHOST-SCSI代码分析(2)VHOST SCSI驱动分析

在HOST内核中创建/dev/vhost-scsi&#xff0c;并提供用户态相关接口&#xff0c;在文件driver/vhost/scsi.c中。 对于/dev/vhost-scsi的ioctl调用包含如下类型&#xff1a; &#xff08;1&#xff09;VRING相关的系统调用 &#xff08;2&#xff09;VHOST SCSI相关的系统调用 …