• ARM Linux DIY(十二)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
    
    • 1
    • 2
    • 3

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    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 
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    游戏手柄调试

    插入游戏手柄

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行游戏

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

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

    不过,监听 /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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

    // 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    然后将各个按键值改正确

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

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

  • 相关阅读:
    【Servlet】2:认识一下Web服务器——Tomcat
    [图像处理] 计算n条线段的交点个数
    Python 学习----基础语法1
    如何排版一篇优秀的公众号文章呢?
    centos7 install postgres-15
    MCE | HIV 衣壳蛋白有望成为 HIV 治疗新靶标
    python excel 读取及写入固定格式
    python爬虫面试题集锦及答案
    day10--232.用栈实现队列+ 225. 用队列实现栈+20. 有效的括号+ 1047. 删除字符串中的所有相邻重复项
    客户文章|南方医科大学李克玄团队破解肠道宏病毒与心肌病关系
  • 原文地址:https://blog.csdn.net/lyndon_li/article/details/132866791