对比了很多种,开源的 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 ;
}
}

arm 2440 linux 应用程序 nes 红白机模拟器 第1篇的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. nes 红白机模拟器 第1篇

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

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

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

随机推荐

  1. javascript函数小练习

    求n-m之间数据的和 <script> function num(n,m){ var sum=0; for (var i = n; i <= m; i++) { sum+=i; } ...

  2. mysql, count函数容易曲解的地方

    统计count(*), 数量为9行; 统计count(abandonAddTime), 数量为8; 统计count(abandonUserName), 数量为9行; count(), 不能统计null ...

  3. 转:Egret社区翻译的《TypeScript语言手册》

      <TyptScript语言手册>第1章-介绍<TypeScript语言手册>第2章-基本概念<TypeScript语言手册>第3章-类型<TypeScri ...

  4. Mock之easymock, powermock, and mockito

    easymock, powermock, and mockito Easymock Class Mocking Limitations To be coherent with interface mo ...

  5. 论文笔记(1)——《Where's Wally?Precise User Discovery Attacks in Location Proximity Services》

    Abstract: 位置相近服务在社交和移动网络的广泛使用是基于可用性和用户隐私的平衡,但引发了三角定位攻击的风险.文章系统化地讨论了此类攻击的防范,包括问题在不同临近模型下的形式化,针对不同模型的有 ...

  6. js获取当前时间戳 不需毫秒数

    var timestamp = Date.parse(new Date())/1000;

  7. ASP.Net的两种开发模式

    一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/bl ...

  8. windows系统IIS环境下如何部署MVC项目

    首先打开IIS:第一步:添加MVC程序映射 打开其中的:处理程序映射,如下图: 点击界面右边操作中的:添加脚本映射,弹出下图: 请求路径:*           可执行文件:c:/Windows/Mi ...

  9. Java基础——基本类型和包装类、基本类型和字符串之间的转换

    基本类型和包装类之间的转换 基本类型和包装类之间经常需要互相转换,以 Integer 为例(其他几个包装类的操作雷同哦): 在 JDK1.5 引入自动装箱和拆箱的机制后,包装类和基本类型之间的转换就更 ...

  10. 做个体面有尊严的IT人【转自界面】

    向老罗致敬,好人终有好报: 转自网站:界面-http://www.jiemian.com/article/231843.html [华盛顿] 史蒂夫·马奎斯隐居在华盛顿郊外的一栋小木屋里,没有电视.没 ...