侧边栏壁纸
博主头像
xiaoming博主等级

累死自己,卷死别人,为了小刘而努力!!!

  • 累计撰写 24 篇文章
  • 累计创建 7 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

IMX6ULL 移植 NES 游戏

Administrator
2024-01-10 / 0 评论 / 0 点赞 / 26 阅读 / 25463 字 / 正在检测是否收录...

1. 前言

InfoNES 是一款经典的任天堂娱乐系统(NES)模拟器,旨在让用户在现代计算机上重温80年代和90年代初期的经典 NES 游戏。该模拟器提供了高度准确的 NES 硬件仿真,支持大多数 NES 游戏,并提供了一种真实的游戏体验。InfoNES 具有用户友好的界面和简单的操作,使得用户可以轻松加载并玩经典的 NES 游戏。无论是想要怀旧,还是想要尝试一些传统的游戏,InfoNES 都为用户提供了一个便捷的平台,让他们沉浸在这些标志性的8位游戏中,体验游戏历史的魅力。

2. 下载

下载启动器源码:https://github.com/nejidev/arm-NES-linux

3. 解压

sudo unzip arm-NES-linux-master.zip

4. 配置源码

源码的编译是在编译完成的 buildroot 文件系统下完成的,必须使能 alsa-lib 和 alsa-utils 才可以使用

1、新建一个work文件夹

mkdir /linux/work

2、进入到源码中的 linux 目录下

cd arm-NES-linux-master/linux

3、修改Makefile文件:vim Makefile

CC = /home/linux/buildroot-2023.11/output/host/bin/arm-linux-gnueabihf-gcc
TARBALL = InfoNES08J

# InfoNES
.CFILES =	./../K6502.cpp \
		./../InfoNES.cpp \
		./../InfoNES_Mapper.cpp \
		./../InfoNES_pAPU.cpp \
		./InfoNES_System_Linux.cpp joypad_input.cpp

.OFILES	=	$(.CFILES:.cpp=.o)

CCFLAGS =  -O2 -fsigned-char -I/home/linux/buildroot-2023.11/output/staging/usr/include
LDFILGS = -lstdc++ -L/home/linux/buildroot-2023.11/output/staging/usr/lib       # gcc3.x.x

all: InfoNES

InfoNES: $(.OFILES)
	$(CC) $(INCLUDES) -o $@ $(.OFILES) $(LDFILGS) -lm -lpthread -lasound

.cpp.o:
	$(CC) $(INCLUDES) -c $(CCFLAGS) $*.cpp  -o $@

clean:
	rm -f $(.OFILES) ../*~ ../*/*~ core

cleanall:
	rm -f $(.OFILES) ../*~ ../*/*~ core InfoNES

release: clean all

tar:
	( cd ..; \
	tar cvf $(TARBALL).tar ./*; \
	gzip $(TARBALL).tar \
	)

install:
	install ./InfoNES /linux/work

在 CCFLAGS 后面增加 alsa 的头文件目录(该目录在bulidroot/output那里例如)

-I/home/linux/buildroot-2023.11/output/staging/usr/include

在 LDFILGS 增加 alsa 的 lib 文件目录(和上面一样)

-L/home/linux/buildroot-2023.11/output/staging/usr/lib

修改最上面的 CC 为 bulidroot 里面的 gcc

/home/linux/buildroot-2023.11/output/host/bin/arm-linux-gnueabihf-gcc

4、更改最后的 install 那里为前面建立的 work 目录

install ./InfoNES /linux/work

5、修改 linux/InfoNES_System_Linux.cpp 文件中的 static int lcd_fb_display_px 函数(调整 spi 屏幕的颜色):

static int lcd_fb_display_px(WORD color, int x, int y)
{
    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;
}

修改为:

static int lcd_fb_display_px(WORD color, int x, int y)
{
    unsigned char  *pen8;
    unsigned short *pen16;

    unsigned char r, g, b;
    r = ((color >> 10) & 0x1f);
    g = ((color >> 5) & 0x3f);
    b = (color & 0x1f);

    color = r<<11|g<<6|b;
    pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
    pen16 = (unsigned short *)pen8;
    *pen16 = color;

    return 0;
}

如果不改的话:
在这里插入图片描述

改了颜色就好一些:
在这里插入图片描述

6、声音实现

实现这个声音支持的前提是,板子上得有基于alsa框架的音频驱动且功能正常。否则以下这些实现里需要全部留空,不用实现。驱动不正常还没有留空运行游戏会直接卡死。

/*===================================================================*/
/*                                                                   */
/*        InfoNES_SoundInit() : Sound Emulation Initialize           */
/*                                                                   */
/*===================================================================*/
void InfoNES_SoundInit( void )
{

}
 
/*===================================================================*/
/*                                                                   */
/*        InfoNES_SoundOpen() : Sound Open                           */
/*                                                                   */
/*===================================================================*/
int InfoNES_SoundOpen( int samples_per_sync, int sample_rate )
{
	// sample_rate 采样率 44100
	// samples_per_sync  735
	// 采样率 / 8 * 声道数 = 44100 / 8 * 1 = 5512.5
	// 8位 声音
	/*
	声道数 1
    采样率 44100
    采样位数 8
    每次播放块大小(NES  APU 每次生成一块)735
	*/
	unsigned int rate      = sample_rate;
	snd_pcm_hw_params_t *hw_params;

	if(0 > snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) 
	{
		printf("snd_pcm_open err\n");
		return -1;
	}
	printf("snd_pcm_open ok!\nsamples_per_sync=%d,sample_rate=%d\n",samples_per_sync,sample_rate);

	if(0 > snd_pcm_hw_params_malloc(&hw_params))
	{
		printf("snd_pcm_hw_params_malloc err\n");
		return -1;
	}

	if(0 > snd_pcm_hw_params_any(playback_handle, hw_params))
	{
		printf("snd_pcm_hw_params_any err\n");
		return -1;
	}
	if(0 > snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) 
	{
		printf("snd_pcm_hw_params_any err\n");
		return -1;
	}
 
	//16bit PCM 数据

	if(0 > snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_U8))
	{
		printf("snd_pcm_hw_params_set_format err\n");
		return -1;
	}

	if(0 > snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &rate, 0)) 
	{
		printf("snd_pcm_hw_params_set_rate_near err\n");
		return -1;
	}
 
	//单声道 非立体声
	if(0 > snd_pcm_hw_params_set_channels(playback_handle, hw_params, 1))
	{
		printf("snd_pcm_hw_params_set_channels err\n");
		return -1;
	}
 
	if(0 > snd_pcm_hw_params(playback_handle, hw_params)) 
	{
		printf("snd_pcm_hw_params err\n");
		return -1;
	}

	snd_pcm_hw_params_free(hw_params);

	if(0 > snd_pcm_prepare(playback_handle)) 
	{
		printf("snd_pcm_prepare err\n");
		return -1;
	}

	return 1;
}
 
/*===================================================================*/
/*                                                                   */
/*        InfoNES_SoundClose() : Sound Close                         */
/*                                                                   */
/*===================================================================*/
void InfoNES_SoundClose( void )
{
	snd_pcm_close(playback_handle);
}
 
/*===================================================================*/
/*                                                                   */
/*            InfoNES_SoundOutput() : Sound Output 5 Waves           */
/*                                                                   */
/*===================================================================*/
void InfoNES_SoundOutput( int samples, BYTE *wave1, BYTE *wave2, BYTE *wave3, BYTE *wave4, BYTE *wave5 )
{

	int i;
	int ret;
	unsigned char wav;
	unsigned char *pcmBuf = (unsigned char *)malloc(samples);

	//printf("InfoNES_SoundOutput,samples=%d\n",samples);
	//printf("\n");
	for (i=0; i <samples; i++)
	{
		wav = (wave1[i] + wave2[i] + wave3[i] + wave4[i] + wave5[i]) / 5;
		//单声道 8位数据
		pcmBuf[i] = wav;
		//printf("%02x",wav);
	}
	//printf("\n");
	ret = snd_pcm_writei(playback_handle, pcmBuf, samples);
	if(-EPIPE == ret)
    {
        snd_pcm_prepare(playback_handle);
    }
	free(pcmBuf);
	return ;
}
<已自动折叠>

5. 编译

make clean
make
make install

生成的文件在 work 文件夹下:

InfoNES

然后把这个 InfoNES 拷贝到开板上就可以了。

6. 运行

打开游戏

./InfoNES hdl-chinese.nes

跑起来了!!
在这里插入图片描述

6、添加USB手柄支持

linux kernel 里面编译:

linux menuconfig
     > Device Drivers > Input device support
     	<*>   Joystick interface
      	[x]   Joysticks/Gamepads  --->
     > Device Drivers > HID support > Special HID drivers
      	<*> DragonRise Inc. game controller

重新烧录内核后,插上游戏手柄:/dev/input 下出现了 js0 设备节点

# ls /dev/input
event0 event1 js0

设备节点出来了,但是游戏手柄按键按着没有反应!

写一个用户空间代码测试一下手柄键值:

#include 
#include 
#include 

typedef unsigned int __u32;
typedef short __s16;
typedef unsigned char __u8;

struct js_event {
    __u32 time;     /* event timestamp in milliseconds */
    __s16 value;    /* value */
    __u8 type;      /* event type */
    __u8 number;    /* axis/button number */
};

#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
#define JS_EVENT_AXIS           0x02    /* joystick moved */
#define JS_EVENT_INIT           0x80    /* initial state of device */

int main() {
    int fd = open("/dev/input/js0", O_RDONLY);
    struct js_event e;
    while(1) {
        read(fd, &e, sizeof(e));
        int type = JS_EVENT_BUTTON | JS_EVENT_INIT;
        switch(e.type) {
            case JS_EVENT_AXIS:
                printf("axis number: %d, value: %d, time: %d\n", e.number, e.value, e.time);
                break;
            case JS_EVENT_BUTTON:
                printf("btn: number: %d, value: %d, time: %d\n", e.number, e.value, e.time);
                break;
        }
    }
    close(fd);
    return 0;
}

编译:

arm-linux-gnueabihf-gcc test.c -o joytest

拷贝到开发板上:

sudo cp joytest /media/liefyuan/rootfs/opt/

测试:
在这里插入图片描述

游戏手柄按键 读出的键值
L1 btn: number: 4, value: 1, time: 198640
btn: number: 4, value: 0, time: 198850
L2 btn: number: 6, value: 1, time: 221840
btn: number: 6, value: 0, time: 222000
R1 btn: number: 5, value: 1, time: 255670
btn: number: 5, value: 0, time: 255840
R2 btn: number: 7, value: 1, time: 257390
btn: number: 7, value: 0, time: 257470
左方向键上 axis number: 1, value: -32767, time: 51680
axis number: 1, value: 0, time: 51840
左方向键下 axis number: 1, value: 32767, time: 99770
axis number: 1, value: 0, time: 99900
左方向键左 axis number: 0, value: -32767, time: 132060
axis number: 0, value: 0, time: 132150
左方向键右 axis number: 0, value: 32767, time: 156420
axis number: 0, value: 0, time: 156510
SELECT键 btn: number: 8, value: 1, time: 312440
btn: number: 8, value: 0, time: 312600
START键 btn: number: 9, value: 1, time: 313560
btn: number: 9, value: 0, time: 313730
右边数字键1 btn: number: 0, value: 1, time: 460600
btn: number: 0, value: 0, time: 460770
右边数字键2 btn: number: 1, value: 1, time: 461560
btn: number: 1, value: 0, time: 461730
右边数字键3 btn: number: 2, value: 1, time: 463040
btn: number: 2, value: 0, time: 463200
右边数字键4 btn: number: 3, value: 1, time: 463790
btn: number: 3, value: 0, time: 463920

查看一下它的写法:
/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)))
	{
		if(0x2 == e.type)
		{
			/*
			上:
			value:0x8001 type:0x2 number:0x5
			value:0x0 type:0x2 number:0x5
			*/
			if(0x8001 == e.value && 0x5 == e.number)
			{
				joypad |= 1<<4;
			}

			/*下:
			value:0x7fff type:0x2 number:0x5
			value:0x0 type:0x2 number:0x5
			*/
			if(0x7fff == e.value && 0x5 == e.number)
			{
				joypad |= 1<<5;
			}
			//松开
			if(0x0 == e.value && 0x5 == e.number)
			{
				joypad &= ~(1<<4 | 1<<5);
			}

			/*左:
			value:0x8001 type:0x2 number:0x4
			value:0x0 type:0x2 number:0x4
			*/
			if(0x8001 == e.value && 0x4 == e.number)
			{
				joypad |= 1<<6;
			}

			/*右:
			value:0x7fff type:0x2 number:0x4
			value:0x0 type:0x2 number:0x4
			*/
			if(0x7fff == e.value && 0x4 == e.number)
			{
				joypad |= 1<<7;
			}
			//松开
			if(0x0 == e.value && 0x4 == e.number)
			{
				joypad &= ~(1<<6 | 1<<7);
			}
		}

		if(0x1 == e.type)
		{
			/*选择:
			value:0x1 type:0x1 number:0xa
			value:0x0 type:0x1 number:0xa
			*/
			if(0x1 == e.value && 0xa == e.number)
			{
				joypad |= 1<<2;
			}
			if(0x0 == e.value && 0xa == e.number)
			{
				joypad &= ~(1<<2);
			}

			/*开始:
			value:0x1 type:0x1 number:0xb
			value:0x0 type:0x1 number:0xb
			*/
			if(0x1 == e.value && 0xb == e.number)
			{
				joypad |= 1<<3;
			}
			if(0x0 == e.value && 0xb == e.number)
			{
				joypad &= ~(1<<3);
			}

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

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

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

			/*Y
			value:0x1 type:0x1 number:0x4
			value:0x0 type:0x1 number:0x4
		 	*/
		 	if(0x1 == e.value && 0x4 == e.number)
			{
				joypad |= 1<<1;
			}
			if(0x0 == e.value && 0x4 == e.number)
			{
				joypad &= ~(1<<1);
			}
		}
		return joypad;
	}
	return -1;
}
<已自动折叠>

调试了一下:

# ./InfoNES Tankwar.nes
/dev/input/js0 dev node ok!
fb width:800 height:480
type: 129, axis number: 0, value: 0, time: -214620
type: 129, axis number: 1, value: 0, time: -214620
type: 129, axis number: 2, value: 0, time: -214620
type: 129, axis number: 3, value: 0, time: -214620
type: 129, axis number: 4, value: 0, time: -214620
type: 129, axis number: 5, value: 0, time: -214620
type: 129, axis number: 6, value: 0, time: -214620
type: 129, axis number: 7, value: 0, time: -214620
type: 129, axis number: 8, value: 0, time: -214620
type: 129, axis number: 9, value: 0, time: -214620
type: 129, axis number: 10, value: 0, time: -214620
type: 129, axis number: 11, value: 0, time: -214620
type: 130, axis number: 0, value: 0, time: -214620
type: 130, axis number: 1, value: 0, time: -214620
type: 130, axis number: 2, value: 0, time: -214620
type: 130, axis number: 3, value: 0, time: -214620

按键是可以获得键值的!!

看了一下逻辑,是键值没有对上

改一下:/linux/joypad_input.cpp 文件的这个函数就可以适配我的游戏手柄了

static int USBjoypadGet(void)
{
	/**
	 * FC joypad bitmap 1Byte==8bits
	 * 0  1   2       3       4    5      6     7
	 * A  B   Select  Start  Up   Down   Left  Right
	 */
	//USB joypad every time can read 1 bit, so,need static var save last time value
	static unsigned char joypad = 0;
	struct js_event e;
	if(0 < read (USBjoypad_fd, &e, sizeof(e)))
	{
		//printf("type: %d, axis number: %d, value: %d, time: %d\n", e.type, e.number, e.value, e.time);
		if(0x2 == e.type) // axis
		{
			/*
			up:
			value:0x8001 type:0x2 number:0x1
			value:0x0 type:0x2 number:0x1
			*/
			if(0x8001 == e.value && 0x1 == e.number)
			{
				joypad |= 1<<4;
			}

			/*down
			value:0x7fff type:0x2 number:0x1
			value:0x0 type:0x2 number:0x1
			*/
			if(0x7fff == e.value && 0x1 == e.number)
			{
				joypad |= 1<<5;
			}
			//release
			if(0x0 == e.value && 0x1 == e.number)
			{
				joypad &= ~(1<<4 | 1<<5);
			}

			/*left
			value:0x8001 type:0x2 number:0x0
			value:0x0 type:0x2 number:0x0
			*/
			if(0x8001 == e.value && 0x0 == e.number)
			{
				joypad |= 1<<6;
			}

			/*right
			value:0x7fff type:0x2 number:0x0
			value:0x0 type:0x2 number:0x0
			*/
			if(0x7fff == e.value && 0x0 == e.number)
			{
				joypad |= 1<<7;
			}
			//release
			if(0x0 == e.value && 0x0 == e.number)
			{
				joypad &= ~(1<<6 | 1<<7);
			}
		}

		if(0x1 == e.type) // btn
		{
			/*select
			value:0x1 type:0x1 number:0x8
			value:0x0 type:0x1 number:0x8
			*/
			if(0x1 == e.value && 0x8 == e.number)
			{
				joypad |= 1<<2;
			}
			if(0x0 == e.value && 0x8 == e.number)
			{
				joypad &= ~(1<<2);
			}

			/*start
			value:0x1 type:0x1 number:0x9
			value:0x0 type:0x1 number:0x9
			*/
			if(0x1 == e.value && 0x9 == e.number)
			{
				joypad |= 1<<3;
			}
			if(0x0 == e.value && 0x9 == e.number)
			{
				joypad &= ~(1<<3);
			}

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

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

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

			/*Y
			value:0x1 type:0x1 number:0x3
			value:0x0 type:0x1 number:0x3
		 	*/
		 	if(0x1 == e.value && 0x3 == e.number)
			{
				joypad |= 1<<1;
			}
			if(0x0 == e.value && 0x3 == e.number)
			{
				joypad &= ~(1<<1);
			}
		}
		//printf("joypad-value: 0x%02x\n", joypad);
		return joypad;
	}
	return -1;
}
<已自动折叠>

Nice,手柄可以了!完成!

7、添加键盘支持

InfoNes 默认只支持具有专有驱动的游戏手柄和一种 USB 通用手柄,但是我们手头只有键盘,所以我们需要添加键盘相关的驱动代码。事实上你下载的代码已经添加了键盘功能,如果想要看看修改了啥,可以看下面。

这里需要修改 linux/joypad_input.cpp 文件,该文件就是用来配置执行游戏操作相关的代码。

添加引用、宏定义、以及全局变量(注意插入的键盘是 event 多少,修改 /dev/input/event0

#include <linux/input.h> //此处需要用到 input_event结构
#define KEYBOARD_DEV "/dev/input/event0" //键盘所在的文件、请根据实际情况进行调整
……
static int joypad_fd;
static int USBjoypad_fd;
static int keyboard_fd;  //新增加的用于存储键盘的句柄
static PT_JoypadInput g_ptJoypadInputHead;
……

接下来是添加键盘结构体,以及相关初始化、释放、获取值相关的代码。

这里我们重点看一下 KeyBoardGet() ,在 nes 游戏中我们只需要配置 8 个键就可以了,对应如下表所示:

img

代码如下:

//****************************keyBoard****************************************

static int KeyBoardGet(void)
{
    /**
     * FC手柄 bit 键位对应关系 真实手柄中有一个定时器,处理 连A  连B 
     * 0  1   2       3       4    5      6     7
     * A  B   Select  Start  Up   Down   Left  Right
     * 
     * o  p   <space> <Enter> w   s      a      d
     * 24 25  57      28      17  31    30     32
     * 
     * 来自 /usr/include/linux/input-event-codes.h  
     */
    //因为 USB 手柄每次只能读到一位键值 所以要有静态变量保存上一次的值
    static unsigned char joypad = 0;
    struct input_event e; //这里使用标准的input_event结构体
    int result = -1;
    result = read(keyboard_fd, &e, sizeof(struct input_event));
    if (result != sizeof(struct input_event))
    {
        printf("key error %d \n", result);
        return -1;
    }

    //printf("value:%u   type:%u  code:%u ", e.value, e.type, e.code);

    if (0x01 == e.type) //EV_KEY            0x01
    {
        /*上 W */
        if (1 == e.value && 17 == e.code)
        {
            joypad |= 1 << 4;
        }
        if (0 == e.value && 17 == e.code)
        {
            joypad &= ~(1 << 4);
        }

        /*下 S*/
        if (1 == e.value && 31 == e.code)
        {
            joypad |= 1 << 5;
        }
        if (0 == e.value && 31 == e.code)
        {
            joypad &= ~(1 << 5);
        }

        /*左 A*/
        if (1 == e.value && 30 == e.code)
        {
            joypad |= 1 << 6;
        }
        if (0 == e.value && 30 == e.code)
        {
            joypad &= ~(1 << 6);
        }

        /*右 D*/
        if (1 == e.value && 32 == e.code)
        {
            joypad |= 1 << 7;
        }
        if (0 == e.value && 32 == e.code)
        {
            joypad &= ~(1 << 7);
        }

        /*选择 space*/
        if (1 == e.value && 57 == e.code)
        {
            joypad |= 1 << 2;
        }
        if (0 == e.value && 57 == e.code)
        {
            joypad &= ~(1 << 2);
        }

        /*开始 enter*/
        if (1 == e.value && 28 == e.code)
        {
            joypad |= 1 << 3;
        }
        if (0 == e.value && 28 == e.code)
        {
            joypad &= ~(1 << 3);
        }

        /*A O*/
        if (1 == e.value && 24 == e.code)
        {
            joypad |= 1 << 0;
        }
        if (0 == e.value && 24 == e.code)
        {
            joypad &= ~(1 << 0);
        }

        /*B P*/
        if (1 == e.value && 25 == e.code)
        {
            joypad |= 1 << 1;
        }
        if (0 == e.value && 25 == e.code)
        {
            joypad &= ~(1 << 1);
        }
    }
    return joypad;
}

static int KeyBoardDevInit(void)
{
    keyboard_fd = open(KEYBOARD_DEV, O_RDONLY);
    if (-1 == keyboard_fd)
    {
        printf("%s dev not found \r\n", KEYBOARD_DEV);
        return -1;
    }
    return 0;
}

static int KeyBoardDevExit(void)
{
    close(keyboard_fd);
    return 0;
}

static T_JoypadInput KeyBoardInput = {
    KeyBoardDevInit,
    KeyBoardDevExit,
    KeyBoardGet,
};

//********************************************************************
<已自动折叠>

最后我们来注册一下键盘,修改 int InitJoypadInput(void) 函数

int InitJoypadInput(void)
{
    int iErr = 0;
    //iErr = RegisterJoypadInput(&joypadInput);
    //iErr = RegisterJoypadInput(&usbJoypadInput);
    iErr = RegisterJoypadInput(&KeyBoardInput);  //这里我们只注册键盘
    return iErr;
}

修改完成后重新编译就可以用键盘来控制游戏了

8、参考

V3S移植nes游戏模拟器(附带游戏合集)

iMX6ULL应用移植 | 移植 infoNES 模拟器(重玩经典NES游戏)

Kevincoooool/KS_V3S)

https://whycan.com/t_5139.html#p52283

0

评论区