对比了很多种,开源的 NES 模拟器 VirtuaNES , nestopia , FakeNES , FCEUX , InfoNES , LiteNES

最后决定使用 LiteNES 进行移值,它是由 mynes 移值而来。LiteNES 对 mynes 代码进行整理兼容了 C99 标准,编译时无警告。

https://github.com/NJUOS/LiteNES

https://github.com/yaglo/mynes

LiteNES , mynes  基于 Allegro ,Allegro 是一种提供底层画图,输入,定时器等支持的库。

LiteNES 全部抽象提取代码到 一个 hal.c 文件里面,修改移值十分方便。下面是修改后的样子,替换这个文件。

在修改下 Makefile 中的 gcc 改为 arm-linux-gcc 编译 即可在板子上出现 Game 画面了(经过测试,发现支持的游戏不多,有的载加不出来)

NES 移值第1篇,仅能出现画面。以后会更新添加声音,多线程,输入等。现在只为能显示出画面。

hal.c :

 /*
This file present all abstraction needed to port LiteNES.
(The current working implementation uses allegro library.) To port this project, replace the following functions by your own:
1) nes_hal_init()
Do essential initialization work, including starting a FPS HZ timer. 2) nes_set_bg_color(c)
Set the back ground color to be the NES internal color code c. 3) nes_flush_buf(*buf)
Flush the entire pixel buf's data to frame buffer. 4) nes_flip_display()
Fill the screen with previously set background color, and
display all contents in the frame buffer. 5) wait_for_frame()
Implement it to make the following code is executed FPS times a second:
while (1) {
wait_for_frame();
do_something();
} 6) int nes_key_state(int b)
Query button b's state (1 to be pressed, otherwise 0).
The correspondence of b and the buttons:
0 - Power
1 - A
2 - B
3 - SELECT
4 - START
5 - UP
6 - DOWN
7 - LEFT
8 - RIGHT
*/
#include "hal.h"
#include "fce.h"
#include "common.h" /**
* allegro API 不明白的看文档
* https://www.allegro.cc/manual/5/index.html
*/
/* lcd 操作相关 头文件 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h> static int fb_fd;
static unsigned char *fb_mem;
static int px_width;
static int line_width;
static int screen_width;
static struct fb_var_screeninfo var; static int lcd_fb_display_px(int color, int x, int y)
{
unsigned char *pen8;
unsigned short *pen16; unsigned char r,g,b; pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
pen16 = (unsigned short *)pen8; //合并为 565 格式 16bbp
r = (color>>) & 0xff;
g = (color>>) & 0xff;
b = (color>>) & 0xff;
*pen16 = (r>>)<< | (g>>)<< | (b>>); return ;
} //调色板转16进行32位颜色
static int pal2color(pal pal)
{
int color = ;
color = pal.r << | pal.g << | pal.b;
return color;
} static int lcd_fb_init()
{
//如果使用 mmap 打开方式 必须是 读写方式
fb_fd = open("/dev/fb0", O_RDWR);
if(- == fb_fd)
{
printf("cat't open /dev/fb0 \n");
return -;
}
//获取屏幕参数
if(- == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
{
close(fb_fd);
printf("cat't ioctl /dev/fb0 \n");
return -;
}
//计算参数
px_width = var.bits_per_pixel / ;
line_width = var.xres * px_width;
screen_width = var.yres * line_width; fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, );
if(fb_mem == (void *)-)
{
close(fb_fd);
printf("cat't mmap /dev/fb0 \n");
return -;
}
//清屏
memset(fb_mem, , screen_width);
return ;
} /* Wait until next allegro timer event is fired. */
void wait_for_frame()
{
//休眠 FPS = 60 * 1000 毫秒
usleep(/FPS*);
} /* Set background color. RGB value of c is defined in fce.h */
void nes_set_bg_color(int c)
{
//画背景颜色
int i,j;
for(i=; i<SCREEN_WIDTH; i++)
{
for(j=; j<SCREEN_HEIGHT; j++)
{
lcd_fb_display_px(pal2color(palette[c]), i, j);
}
}
} /* Flush the pixel buffer */
void nes_flush_buf(PixelBuf *buf)
{
Pixel *p;
int i,x,y,color;
for (i = ; i < buf->size; i++)
{
p = &buf->buf[i];
x = p->x;
y = p->y; color = pal2color(palette[p->c]);
lcd_fb_display_px(color, x, y);
lcd_fb_display_px(color, x+, y);
lcd_fb_display_px(color, x, y+);
lcd_fb_display_px(color, x+, y+);
}
} /* Initialization:
(1) start a 1/FPS Hz timer.
(2) register fce_timer handle on each timer event */
void nes_hal_init()
{
/**
* 需要完成的事情
* 1,初始化 lcd
* 2,初始化 定时器 先做简单的直接用系统延时
*/
if(- == lcd_fb_init())
{
printf("lcd fb init error \n");
return ;
}
} /* Update screen at FPS rate by allegro's drawing function.
Timer ensures this function is called FPS times a second. */
void nes_flip_display()
{
//设置64种颜色值 不必设置
} /* Query a button's state.
Returns 1 if button #b is pressed. */
int nes_key_state(int b)
{
switch (b)
{
case : // On / Off
return ;
case : // A
return ;
case : // B
return ;
case : // SELECT
return ;
case : // START
return ;
case : // UP
return ;
case : // DOWN
return ;
case : // LEFT
return ;
case : // RIGHT
return ;
default:
return ;
}
}

nes 红白机模拟器 第1篇的更多相关文章

  1. nes 红白机模拟器 第7篇 编译使用方法

    模拟器,基于 InfoNES ,作者添加修改以下功能: 1, joypad 真实手柄驱动程序(字符型设备驱动) 2,原始图像只有256*240 ,添加 图像放大算法,这里实现了2种,a, 最近邻插值 ...

  2. arm 2440 linux 应用程序 nes 红白机模拟器 第1篇

    对比了很多种,开源的 NES 模拟器 VirtuaNES , nestopia , FakeNES , FCEUX , InfoNES , LiteNES 最后决定使用 LiteNES 进行移值,它是 ...

  3. arm 2440 linux 应用程序 nes 红白机模拟器 第4篇 linux 手柄驱动支持

    小霸王学习机的真实手柄,实测CPU 占用 80% 接线图: 手柄读时序: joypad.c 驱动: 普通的字符设备驱动. #include <linux/module.h> #includ ...

  4. arm 2440 linux 应用程序 nes 红白机模拟器 第2篇 InfoNES

    InfoNES 支持 map ,声音,代码比较少,方便 移值. 在上个 LiteNES  的基础上,其实不到半小时就移值好了这个,但问题是,一直是黑屏.InfoNES_LoadFrame ()  Wo ...

  5. nes 红白机模拟器 第6篇 声音支持

    InfoNES 源码中并没有包含 linux 的声音支持. 但提供 wince 和 win 的工程,文件,通过分析,win 的 DirectSound 发声,在使用 linux ALSA 实现. 先使 ...

  6. nes 红白机模拟器 第5篇 全屏显示

    先看一下效果图 放大的原理是使用最初级的算法,直接取对应像素法. /*================================================================= ...

  7. nes 红白机模拟器 第4篇 linux 手柄驱动支持

    小霸王学习机的真实手柄,实测CPU 占用 80% 接线图: 手柄读时序: joypad.c 驱动: 普通的字符设备驱动. #include <linux/module.h> #includ ...

  8. nes 红白机模拟器 第2篇 InfoNES

    InfoNES 支持 map ,声音,代码比较少,方便 移值. 在上个 LiteNES  的基础上,其实不到半小时就移值好了这个,但问题是,一直是黑屏.InfoNES_LoadFrame ()  Wo ...

  9. nes 红白机模拟器 第3篇 游戏手柄测试 51 STM32

    手柄使用的是 CD4021 ,datasheet 上说支持 3V - 15V . 因为手柄是 5V 供电,2440 开发板上是GPIO 3.3V 电平,STM32 GPIO 也是 3.3V (也兼容5 ...

随机推荐

  1. 68)PHP,cookie的详细属性和有效期

    (1)cookie的有效期: 默认:会话周期结束(就是浏览器关闭),默认情况下,cookie会在浏览器关闭时失效,这种cookie是 临时cookie或者叫会话. 支持设置有效期,setcookie的 ...

  2. Linux下安装mysql(yun方式)

    1.进入下载好的mysql版本 cd /usr/local/mysql 2.解压安装包 tar -xzvf mysql-5.7.11.tar.gz 3.改名 直接改或者 mv  文件名 要改的文件名m ...

  3. 关于RFC

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/byxdaz/article/details/557902关于RFC(Request For Comm ...

  4. java中的二维数组基础知识

    二维数组基本知识,毕竟常见的有:概念,初始化,遍历 概念: 理解二维数组,首先要先理解一维数组是什么.一维数组是个容器,存储相同数据类型的容器(这里不再做一位数组的具体介绍).二维数组就是用来存储一维 ...

  5. C语言学习笔记之字符串拼接的2种方法——strcat、sprintf

    本文为原创文章,转载请标明出处 1. 使用strcat进行字符串拼接 #include <stdio.h> #include <stdlib.h> #include <s ...

  6. 在腾讯云服务器上安装JDK+Tomcat并启动tomcat

    由于Java web项目需要使用到tomcat所以决定在腾讯云服务器(centos7.X)上安装JDK和tomcat,来部署我们的项目. 准备工具: 云服务器:centos7.x+ 本地连接服务器:X ...

  7. js事件节流

    背景:在监听浏览器滚动条的scroll事件时该事件会触发很多次,这样当快速滚动时会有很差的性能,所以要限制事件触发的频率,可以防抖和节流,这里我记录简单的节流方法 <!DOCTYPE html& ...

  8. 将js进行到底:node学习1

    废话:自高中以来一直对编程充满激情,磨剑五年,如今要毕业了,我不想用我已经擅长的知识敷衍,而想以一个全新的领域去面向我的毕设--是时候学习一下node.js node.js基础 对于JavaScrip ...

  9. 用shell脚本新建文件并自动生成头说明信息

    目标: 新建文件后,直接给文件写入下图信息 代码实现: [root@localhost test]# vi AutoHead.sh #!/bin/bash #此程序的功能是新建shell文件并自动生成 ...

  10. github 下载部分代码

    作者:知乎用户链接:https://www.zhihu.com/question/25369412/answer/96174755来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...