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

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

  1 /*
  2 This file present all abstraction needed to port LiteNES.
  3   (The current working implementation uses allegro library.)
  4
  5 To port this project, replace the following functions by your own:
  6 1) nes_hal_init()
  7     Do essential initialization work, including starting a FPS HZ timer.
  8
  9 2) nes_set_bg_color(c)
 10     Set the back ground color to be the NES internal color code c.
 11
 12 3) nes_flush_buf(*buf)
 13     Flush the entire pixel buf‘s data to frame buffer.
 14
 15 4) nes_flip_display()
 16     Fill the screen with previously set background color, and
 17     display all contents in the frame buffer.
 18
 19 5) wait_for_frame()
 20     Implement it to make the following code is executed FPS times a second:
 21         while (1) {
 22             wait_for_frame();
 23             do_something();
 24         }
 25
 26 6) int nes_key_state(int b)
 27     Query button b‘s state (1 to be pressed, otherwise 0).
 28     The correspondence of b and the buttons:
 29       0 - Power
 30       1 - A
 31       2 - B
 32       3 - SELECT
 33       4 - START
 34       5 - UP
 35       6 - DOWN
 36       7 - LEFT
 37       8 - RIGHT
 38 */
 39 #include "hal.h"
 40 #include "fce.h"
 41 #include "common.h"
 42
 43 /**
 44  * allegro API 不明白的看文档
 45  * https://www.allegro.cc/manual/5/index.html
 46  */
 47 /* lcd 操作相关 头文件 */
 48 #include <sys/types.h>
 49 #include <sys/stat.h>
 50 #include <fcntl.h>
 51 #include <linux/fb.h>
 52 #include <sys/ioctl.h>
 53 #include <unistd.h>
 54 #include <string.h>
 55 #include <sys/mman.h>
 56
 57 static int fb_fd;
 58 static unsigned char *fb_mem;
 59 static int px_width;
 60 static int line_width;
 61 static int screen_width;
 62 static struct fb_var_screeninfo var;
 63
 64 static int lcd_fb_display_px(int color, int x, int y)
 65 {
 66     unsigned char  *pen8;
 67     unsigned short *pen16;
 68
 69     unsigned char r,g,b;
 70
 71     pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
 72     pen16 = (unsigned short *)pen8;
 73
 74     //合并为 565 格式 16bbp
 75     r = (color>>16) & 0xff;
 76     g = (color>>8) & 0xff;
 77     b = (color>>0) & 0xff;
 78     *pen16 = (r>>3)<<11 | (g>>2)<<5 | (b>>3);
 79
 80     return 0;
 81 }
 82
 83 //调色板转16进行32位颜色
 84 static int pal2color(pal pal)
 85 {
 86     int color = 0;
 87     color = pal.r << 16 | pal.g <<8 | pal.b;
 88     return color;
 89 }
 90
 91 static int lcd_fb_init()
 92 {
 93     //如果使用 mmap 打开方式 必须是 读定方式
 94     fb_fd = open("/dev/fb0", O_RDWR);
 95     if(-1 == fb_fd)
 96     {
 97         printf("cat‘t open /dev/fb0 \n");
 98         return -1;
 99     }
100     //获取屏幕参数
101     if(-1 == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
102     {
103         close(fb_fd);
104         printf("cat‘t ioctl /dev/fb0 \n");
105         return -1;
106     }
107     //计算参数
108     px_width = var.bits_per_pixel / 8;
109     line_width = var.xres * px_width;
110     screen_width = var.yres * line_width;
111
112     fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
113     if(fb_mem == (void *)-1)
114     {
115         close(fb_fd);
116         printf("cat‘t mmap /dev/fb0 \n");
117         return -1;
118     }
119     //清屏
120     memset(fb_mem, 0 , screen_width);
121     return 0;
122 }
123
124 /* Wait until next allegro timer event is fired. */
125 void wait_for_frame()
126 {
127     //休眠 FPS = 60 * 1000 毫秒
128     usleep(1/FPS*1000);
129 }
130
131 /* Set background color. RGB value of c is defined in fce.h */
132 void nes_set_bg_color(int c)
133 {
134     //画背景颜色
135     int i,j;
136     for(i=0; i<SCREEN_WIDTH; i++)
137     {
138         for(j=0; j<SCREEN_HEIGHT; j++)
139         {
140             lcd_fb_display_px(pal2color(palette[c]), i, j);
141         }
142     }
143 }
144
145 /* Flush the pixel buffer */
146 void nes_flush_buf(PixelBuf *buf)
147 {
148     Pixel *p;
149     int i,x,y,color;
150     for (i = 0; i < buf->size; i++)
151     {
152            p = &buf->buf[i];
153            x = p->x;
154         y = p->y;
155
156         color = pal2color(palette[p->c]);
157         lcd_fb_display_px(color, x, y);
158         lcd_fb_display_px(color, x+1, y);
159         lcd_fb_display_px(color, x, y+1);
160         lcd_fb_display_px(color, x+1, y+1);
161         }
162 }
163
164 /* Initialization:
165    (1) start a 1/FPS Hz timer.
166    (2) register fce_timer handle on each timer event */
167 void nes_hal_init()
168 {
169     /**
170      * 需要完成的事情
171      * 1,初始化 lcd
172      * 2,初始化 定时器 先做简单的直接用系统延时
173      */
174     if(-1 == lcd_fb_init())
175     {
176         printf("lcd fb init error \n");
177         return ;
178     }
179 }
180
181 /* Update screen at FPS rate by allegro‘s drawing function.
182    Timer ensures this function is called FPS times a second. */
183 void nes_flip_display()
184 {
185     //设置64种颜色值 不必设置
186 }
187
188 /* Query a button‘s state.
189    Returns 1 if button #b is pressed. */
190 int nes_key_state(int b)
191 {
192     switch (b)
193     {
194         case 0: // On / Off
195             return 1;
196         case 1: // A
197             return 1;
198         case 2: // B
199             return 1;
200         case 3: // SELECT
201             return 1;
202         case 4: // START
203             return 1;
204         case 5: // UP
205             return 1;
206         case 6: // DOWN
207             return 1;
208         case 7: // LEFT
209             return 1;
210         case 8: // RIGHT
211             return 1;
212         default:
213             return 1;
214     }
215 }
时间: 2025-01-06 22:34:02

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

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

InfoNES 支持 map ,声音,代码比较少,方便 移值. 在上个 LiteNES  的基础上,其实不到半小时就移值好了这个,但问题是,一直是黑屏.InfoNES_LoadFrame ()  WorkFrame 中一直是 0 . 解决的过程很漫长,最终看到 说是 ADS 中 有符号 无符号的问题,但是 这里用的是 makefile 不是 ADS ,试着改了 makefile 加上 CCFLAGS =  -O2 -fsigned-char . 终于有输出了,性能还算不错. InfoNES 源码

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

小霸王学习机的真实手柄,实测CPU 占用 80% 接线图: 手柄读时序: joypad.c 驱动: 普通的字符设备驱动. 1 #include <linux/module.h> 2 #include <linux/kernel.h> 3 #include <linux/fs.h> 4 #include <linux/init.h> 5 #include <linux/delay.h> 6 #include <asm/uaccess.h>

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

模拟器,基于 InfoNES ,作者添加修改以下功能: 1, joypad 真实手柄驱动程序(字符型设备驱动) 2,原始图像只有256*240 ,添加 图像放大算法,这里实现了2种,a, 最近邻插值 b, 双线性插值 (因为2440 速度太慢,采用双线性插值时,大概要3秒算一帧,等以后用 4412 在测试实际效果,本文还会更新) 3,声音支持,原 InfoNES 中,使用 oss 播放声音,添加 使用 alsa 播放支持, 4,LCD显示支持,原 InfoNES 中,使用 Gtk进行显示,作者添

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

InfoNES 源码中并没有包含 linux 的声音支持. 但提供 wince 和 win 的工程,文件,通过分析,win 的 DirectSound 发声,在使用 linux ALSA 实现. 先使用 DirectSound 模仿写一个 播放 wav 的程序. 为了简单,我这里使用  vc++ 6.0 (vs2015 实在太大了,电脑装上太卡). 新建一个 mfc exe 项目,基于对话框.放一个按钮,双击添加事件. 添加头文件引用#include <mmsystem.h>#pragma c

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

手柄使用的是 CD4021 ,datasheet 上说支持 3V - 15V . 因为手柄是 5V 供电,2440 开发板上是GPIO 3.3V 电平,STM32 GPIO 也是 3.3V (也兼容5V)电平. 所以先在 STM32 上测试能用后,在接到 2440 开发板上. 正好是 8个键值,用来点 8个 LED .按下一个键,就会亮一个灯. c51 : 1 #include <reg52.h> 2 3 sbit CLK = P2 ^ 2; 4 sbit LATCH = P2 ^ 1; 5

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

先看一下效果图,全屏是全了,但是效果非常很一般(差) 放大的原理是使用最初级的算法,直接取对应像素法. 1 /** 2 * 生成zoom 缩放表 3 */ 4 int make_zoom_tab() 5 { 6 int i; 7 zoom_x_tab = (int *)malloc(sizeof(int) * NES_DISP_WIDTH); 8 if(NULL == zoom_x_tab) 9 { 10 printf("make zoom_x_tab error\n"); 11 re

当年击败红白机的奇葩怪招 后来玩山寨的都在学

百合一.千合一,是山寨者往往第一时间想到的法子,无限集成近乎全套功能于一身,甭管好坏.但这往往也就忽悠下好奇的围观群众. 文/张书乐    原载于<人民邮电报>2015年10月23日<乐游记>专栏 红白机被以小霸王为首的中国"山寨"游戏机们击溃,一个关键原因就在于竞争对手的终端产品都能够毫无阻碍地运行红白机的游戏卡带.短短3年的"山寨"之路,让小霸王成功突破年产值10亿元大关.当时,面对正在变成世界工厂.劳动力成本极为低廉的中国对手,且在知识

童年红白机?FC经典游戏600合集for mac

曾经的"小霸王"游戏机,让我们许多80年后.90后度过了一个欢乐愉快的童年,虽然如今这类游戏机和卡带几乎已经退出游戏市场,但经典永远留在了我们这一代人心中.今天给大家分享的小霸王FC经典游戏600合集,带你回顾童年,重温经典!希望大家喜欢! 霸王FC经典游戏600合集之部分游戏介绍 1.<超级马里奥兄弟><超级马里奥兄弟>,是任天堂公司开发并于1985年出品的著名横版过关游戏,是游戏奠基之作,这是一款任天堂针对FC主机全力度身订造的游戏.这个游戏被赞誉为电子游戏

linux(ubuntu12.04)下手机真机调试eclipse上的android程序

模拟器太慢了,而且在模拟器上运行程序的效果毕竟还是跟在真机上有点区别的,所以建议大家尽量使用真机调试.把android手机通过usb线连接至电脑,之后步骤如下: 1. 在/etc/udev/rules.d/目录下新建一个51-android.rules文件,文件内容为: SUBSYSTEM == "usb",ENV{DEVTYPE} == "usb_device",MODE = "0666" 2.$ sudo chmod a+rx /etc/ud