当前位置:首页 > 操作系统 > Linux

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 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)!

相关教程推荐

其他课程推荐