当前位置:首页 > 技术 > LINUX > 正文内容

【转】小白自制Linux开发板 十. NES游戏玩起来

Watrt1个月前 (01-06)LINUX1070

1. 开发环境搭建

首先安装gcc,通常情况下,当制作完成Debian文件系统的时候就已经默认集成了,如果没有这是用apt-get 进行安装,然后在命令中输入:

gcc -v

如果显示如下信息

Using built-in specs.COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabi/8/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Debian 8.3.0-6' --with-bugurl=file:///usr/share/doc/gcc-8/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-8 --program-prefix=arm-linux-gnueabi- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-sjlj-exceptions --with-arch=armv5te --with-float=soft --disable-werror --enable-checking=release --build=arm-linux-gnueabi --host=arm-linux-gnueabi --target=arm-linux-gnueabi
Thread model: posix
gcc version 8.3.0 (Debian 8.3.0-6)

就表示我们的小板已经安装了编译器了。

接下来我们就开始移植NES游戏机模拟器程序,这里使用InfoNes,代码下载:

https://files.cnblogs.com/files/twzy/arm-NES-linux-master.zip

InfoNES 音频部分需要alsa相关的组件,大概有两个alsa-utils和 alsa-lib,这个组件我们在音频部分有过了解。

对于alsa-utils可以直接通过  apt-get install alsa-utils  进行安装,此处不做过多细说,但是对于alsa-lib作者并没有在找到可以直接安装的包,所以我们手动编译。

1.1 安装alsa-lib#

首先下载alsa-lib库

 https://files.cnblogs.com/files/twzy/alsa-lib-1.2.5.1.zip

 然后把zip文件上传到到我们的开发板上面,解压进入alsa-lib-1.2.5.1目录中,接下来就是Linux三板斧安装方法:

  • 执行  ./configure  进行项目配置

  • 执行 make  进行编译

  • 执行 make install  进行安装

因为alsa-lib项目较大,我们的小电脑很弱,所以你会等很长时间。

安装完成以后,在目录/usr/include中,就会有个alsa文件夹,里面就有项目使用的头文件。

1.2 安装SDL(可选)#

本节为可选项,因为在墨云编译其他版本的nes模拟器的时候,有要求需要用到这个库,所以这个开发板已经安装了,根据作者经验应该大概率不用安装,读者可以自行决定。

SDL是Simple DirectMedia Layer(简易直控媒体层)的缩写。它是一个跨平台的多媒体库,以用于直接控制底层的多媒体硬件的接口。主要用在开发游戏上!

安装sdl软件

apt-get install libsdl1.2-dev

附加包:

sudo apt-get install libsdl-image1.2-dev
sudo apt-get install libsdl-mixer1.2-dev
sudo apt-get install libsdl-ttf2.0-dev
sudo apt-get install libsdl-gfx1.2-dev

安装完成之后,在目录/usr/include中,就会有个SDL文件夹,里面包含了所需要的头文件。

2. NES项目配置

上面下载nes代码,作者已经完成了下面三个部分的修改,所以直接进入arm-NES-linux-master/linux 目录下执行 make 命令就能直接编译了。

2.1 修改Makefile

修改arm-NES-linux-master/linux/Makefile 文件

vi Makefile

这里我们只需要修改最开始的cc=gcc 就行

 终于不用配置交叉编译工具了,毕竟是小电脑啊 ^_^

2.2 增加键盘输入#

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

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

添加引用、宏定义、以及全局变量

#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个键就可以了,对应如下表所示:

代码如下:

//****************************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;
}

2.3  修改偏色问题

键盘修改完毕,接下来就改一下屏幕偏色的问题,这里只需要修改 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;    //修改InfoNES_System_Linux.cpp文件中的static int lcd_fb_display_px函数(调整spi屏幕的颜色):
    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;
}

接下来就在linux目录下执行

make

命令,等待编译结束就可以在当前目录下看到一个叫InfoNES的软件,这就是编译好的模拟器,接下来执行命令(我的游戏存放在/root/game/目录下)

./InfoNES /root/game/h.nes

不出意外就可以看到如下的画面

所以还不玩起来……

4. 遗留问题

 作者每次写文章的水平是普通的,但是留坑的手法是花样的,本次有两个坑

  • 画面 ~ 在操作游戏的时候、因为FrameBuffer的关系,可以明显看到光标导致的画面异常;

  • 声音 ~ 只能算是听个响,真的;

 所以后续随缘解决吧。

分享给朋友:

相关文章

[转]Linux内核配置和编译过程详解

[转]Linux内核配置和编译过程详解

一、引言: 本文档的内容大部份内容都是从网上收集而来,然后配合一些新的截 图(内核版本:V2.4.19)。在每一配置项后会有一个选择指南的部份,用来指导大家怎么样 根据自己的情况来做相应的选择;还有在每一个大项和文档的最后会有一个经验谈,它是一些高手们在应对问题和处理特有硬件时的一些经验(这个还得靠各位)。 文档最后会发到网上,到时会根据网友们的回复随时进行更新。 我们的目的是让我们有一个全面的、简单明了内核编译帮手。#make mrproper -----删除不必要的文件和...

基于 debootstrap 和 busybox 构建 mini ubuntu

基于 debootstrap 和 busybox 构建 mini ubuntu

最近的工作涉及到服务器自动安装和网络部署操作系统,然后使用 ansible 和 saltsatck 进行配置并安装 openstack 。难点在于服务器的自动安装,由于不单只是通过 PXE 安装服务器,还需要能够安装时进行分区、配置网卡等工作,因此需要在开始安装前,必须先收集服务器的硬件信息。调研了一下目前的开源项目中,提供此类功能的有 tinycorelinux 、 puppet razor-el-mk 可做类似的工作。tinycorelinux 是个很好的工具,整个系统在 PXE 之后在内存...

licheepi_zero开发板 buildroot配置 一键编译

licheepi_zero开发板 buildroot配置 一键编译

开贴记录配置最新buildroot-2018.08.使用buildroot自带工具链一键编译生成uboot,kernel,dtb和rootfs.最新稳定版buildroot下载:buildroot-2018.08.02稳定版我配置好的config文件:配置好的.config本人的开发环境是vmware workstation 15 pro+ubuntu 16.04_x64参照沉鱼的帖子荔枝派Zero V3s开发板入坑记录 (TF/SD卡启动)(主线Linux,主线u-boot)做如下配置:1.t...

制作荔枝派Zero开发板(全志V3s) TF/SD卡启动盘

制作荔枝派Zero开发板(全志V3s) TF/SD卡启动盘

0. 前言近几天买了一块荔枝派0开发板,以及官方配的480×272的屏幕。让我记录一下入坑与采坑过程。1. u-boot的编译git clone https://github.com/Lichee-Pi/u-boot -b v3s-current cd u-boot make ARCH=arm LicheePi_Zero_480x272LCD_defconfig make ARCH=arm CROSS...

荔枝派nano(f1c100s)的SPI-Flash系统编译创建全过程

荔枝派nano(f1c100s)的SPI-Flash系统编译创建全过程

前言本文的目标是创建一个运行在SPI-Flash上的精简系统,附带填一些前人没有提及的坑。在开始之前,请先通读官方教程的即食部分(U-Boot)、Linux编译和SPI-Flash系统的创建部分的教程,并搭建好编译工具链。以下我假设你已经按照上面的教程下载好了U-Boot和Linux内核,并且到Buildroot的官网下载好了Buildroot(但没按教程创建config文件)。SPI-Flash的分区结构以下是我这里的分区结构。你可以自由的分配后面两个分区的大小。ID  S...

Deepin Linux修复grub引导

Deepin Linux修复grub引导

环境说明:一直使用的是Win7+Deepin 15.5。后来全新安装了Win 10,需要修复grub第一步:在Windows操作系统下使用深度官方的U盘启动制作器 制作U盘第二步:开机U盘启动进入Deepin linux安装界面,待进入到安装界面选择语言时,按住Crtl+Alt+F2/F1进入Linux tty终端。并执行以下命令完成修复sudo fdisk -l/*根据查询结果确定deepin 的/目录和/boot目录所在的分区编号*/sudo mount&nbs...

buildroot编译中的问题

buildroot编译中的问题

在编译中遇到flex 报错。一直过不了。后来发现安装flex bison两个包后解决sudo apt-get install flex bison...

LINUX 使用sendmail邮件备份

LINUX 使用sendmail邮件备份

首先安装:sudo apt-get install sendmail然后在终端可以使用mail来发邮件echo "ESP32固件"|mail -s "esp32" -A "./fw.bin" -r "bak@xxx.com" xb100@qq.com注意很有可能收到的邮件在垃圾箱里面。把发件地址加到白 名单中...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。