对比了很多种,开源的 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. VisionPro和Halcon的详细对比

    一.概括的对比 1.1  Halcon的优势 Halcon有着更加低廉的Lisence 1.并且提供更好.更强大的2D和3D的视觉软件库 2.Halcon支持的视觉图像采集设备数量是Visionpro ...

  2. SecureCRT8.1安装破解

    博主本人平和谦逊,热爱学习,读者阅读过程中发现错误的地方,请帮忙指出,感激不尽 一.安装破解 [基本信息] SecureCRT v8.x 注册机,TEAM Z.W.T 出品,MD5 = 44114b9 ...

  3. python-django项目基础-haystack&whoosh&jieba_20191124

    全文检索框架和搜索引擎的安装和配置: 安装全文检索框架,pip install django-haystack, 安装搜索引擎,pip install whoosh settings里面配置 1,注册 ...

  4. The Mean of the Sample Mean|Standard Deviation of the Sample Mean|SE

    7.2  The Mean and Standard Deviation of the Sample Mean Recall that the mean of a variable is denote ...

  5. C++中stoi函数

    作用: 将 n 进制的字符串转化为十进制 头文件: #include <string> 用法: stoi(字符串,起始位置,n进制),将 n 进制的字符串转化为十进制 示例: stoi(s ...

  6. Linux主机下如何查询自己使用的公网IP

    curl http://members.3322.org/dyndns/getip 可以解析出自己是使用哪个公网IP访问外网的

  7. 用JSON报的一个错误java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRuntimeExcep

    以前在做项目的时候就曾接触过JSON的技术,但那个时候是项目经理把所有该配制的都配了,工具类也提供了,如何使用也跟我们说了,那个时候只是觉得很好用,倒没有研究过. 今天自己写了一个JSON的例子,可以 ...

  8. fastdfs+nginx make时报错fatal error:fdfs_define.h: 没有那个文件或目录

    环境: ubuntu 18.04.1 fastdfs-nginx-module_v1.16 root@wang-machine:~/桌面/FastDFS# cd nginx-1.8.1/root@wa ...

  9. phpStrom安装PHP_CodeSniffer检查代码规范

    为什么使用PHP_CodeSniffer 一个开发团队统一的编码风格,有助于他人对代码的理解和维护,对于大项目来说尤其重要. PHP_CodeSniffer是PEAR中的一个用PHP5写的用来检查嗅探 ...

  10. nodejs+vue.js+webpack

    前端: nodejs+vue.js+webpack 后台:ssb(Spring+SpringMVC + mybatis-plus) 开发工具:idea 一.前提 1.安装nodejs 2.安装完nod ...