对比了很多种,开源的 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 57staticint fb_fd;
58static unsigned char *fb_mem;
59staticint px_width;
60staticint line_width;
61staticint screen_width;
62staticstruct fb_var_screeninfo var;
63 64staticint 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 80return0;
81}
82 83//调色板转16进行32位颜色 84staticint pal2color(pal pal)
85{
86int color = 0;
87 color = pal.r << 16 | pal.g <<8 | pal.b;
88return color;
89}
90 91staticint lcd_fb_init()
92{
93//如果使用 mmap 打开方式 必须是 读定方式 94 fb_fd = open("/dev/fb0", O_RDWR);
95if(-1 == fb_fd)
96 {
97 printf("cat‘t open /dev/fb0 n");
98return -1;
99 }
100//获取屏幕参数101if(-1 == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
102 {
103 close(fb_fd);
104 printf("cat‘t ioctl /dev/fb0 n");
105return -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;
111112 fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
113if(fb_mem == (void *)-1)
114 {
115 close(fb_fd);
116 printf("cat‘t mmap /dev/fb0 n");
117return -1;
118 }
119//清屏120 memset(fb_mem, 0 , screen_width);
121return0;
122}
123124/* Wait until next allegro timer event is fired. */125void wait_for_frame()
126{
127//休眠 FPS = 60 * 1000 毫秒128 usleep(1/FPS*1000);
129}
130131/* Set background color. RGB value of c is defined in fce.h */132void nes_set_bg_color(int c)
133{
134//画背景颜色135int i,j;
136for(i=0; i<SCREEN_WIDTH; i++)
137 {
138for(j=0; j<SCREEN_HEIGHT; j++)
139 {
140 lcd_fb_display_px(pal2color(palette[c]), i, j);
141 }
142 }
143}
144145/* Flush the pixel buffer */146void nes_flush_buf(PixelBuf *buf)
147{
148 Pixel *p;
149int i,x,y,color;
150for (i = 0; i < buf->size; i++)
151 {
152 p = &buf->buf[i];
153 x = p->x;
154 y = p->y;
155156 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}
163164/* Initialization:
165 (1) start a 1/FPS Hz timer.
166 (2) register fce_timer handle on each timer event */167void nes_hal_init()
168{
169/**
170 * 需要完成的事情
171 * 1,初始化 lcd
172 * 2,初始化 定时器 先做简单的直接用系统延时
173*/174if(-1 == lcd_fb_init())
175 {
176 printf("lcd fb init error n");
177return ;
178 }
179}
180181/* Update screen at FPS rate by allegro‘s drawing function.
182 Timer ensures this function is called FPS times a second. */183void nes_flip_display()
184{
185//设置64种颜色值 不必设置186}
187188/* Query a button‘s state.
189 Returns 1 if button #b is pressed. */190int nes_key_state(int b)
191{
192switch (b)
193 {
194case0: // On / Off195return1;
196case1: // A197return1;
198case2: // B199return1;
200case3: // SELECT201return1;
202case4: // START203return1;
204case5: // UP205return1;
206case6: // DOWN207return1;
208case7: // LEFT209return1;
210case8: // RIGHT211return1;
212default:
213return1;
214 }
215 }
原文:http://www.cnblogs.com/ningci/p/5618351.html
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!