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, and17 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 - Power30 1 - A31 2 - B32 3 - SELECT33 4 - START34 5 - UP35 6 - DOWN36 7 - LEFT37 8 - RIGHT38 */
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
49 #include
50 #include
51 #include
52 #include
53 #include
54 #include
55 #include
56
57 static intfb_fd;58 static unsigned char *fb_mem;59 static intpx_width;60 static intline_width;61 static intscreen_width;62 static struct fb_var_screeninfo var;63
64 static int lcd_fb_display_px(int color, int x, inty)65 {66 unsigned char *pen8;67 unsigned short *pen16;68
69 unsigned charr,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 intpal2color(pal pal)85 {86 int color = 0;87 color = pal.r << 16 | pal.g <<8 |pal.b;88 returncolor;89 }90
91 static intlcd_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 voidwait_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(intc)133 {134 //画背景颜色
135 inti,j;136 for(i=0; i
145 /*Flush the pixel buffer*/
146 void nes_flush_buf(PixelBuf *buf)147 {148 Pixel *p;149 inti,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 voidnes_hal_init()168 {169 /**170 * 需要完成的事情171 * 1,初始化 lcd172 * 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 voidnes_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(intb)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 }