nes 红白机模拟器 第2篇 InfoNES

InfoNES 支持 map ,声音,代码比较少,方便 移值。

在上个 LiteNES  的基础上,其实不到半小时就移值好了这个,但问题是,一直是黑屏。InfoNES_LoadFrame ()  WorkFrame 中一直是 0 。

解决的过程很漫长,最终看到 说是 ADS 中 有符号 无符号的问题,但是 这里用的是 makefile 不是 ADS ,试着改了 makefile 加上 CCFLAGS =  -O2 -fsigned-char 。

终于有输出了,性能还算不错。

InfoNES 源码 http://www.zophar.net/pocket-pc/nes/infonesft.html

主要修改的是 InfoNES_System_Linux.cpp 和 Makefile

同样的,现在仅实现显示未加输入,声音,全屏等。后期在加。

InfoNES_System_Linux.cpp

  1 /*===================================================================*/
  2 /*                                                                   */
  3 /*  InfoNES_System_Linux.cpp : Linux specific File                   */
  4 /*                                                                   */
  5 /*  2001/05/18  InfoNES Project ( Sound is based on DarcNES )        */
  6 /*                                                                   */
  7 /*===================================================================*/
  8 
  9 /*-------------------------------------------------------------------*/
 10 /*  Include files                                                    */
 11 /*-------------------------------------------------------------------*/
 12 
 13 #include <stdio.h>
 14 #include <stdlib.h>
 15 #include <string.h>
 16 #include <pthread.h>
 17 
 18 #include <sys/types.h>
 19 #include <sys/stat.h>
 20 #include <fcntl.h>
 21 #include <sys/ioctl.h>
 22 #include <unistd.h>
 23 #include <sys/soundcard.h>
 24 
 25 #include "../InfoNES.h"
 26 #include "../InfoNES_System.h"
 27 #include "../InfoNES_pAPU.h"
 28 
 29 //bool define
 30 #define TRUE 1
 31 #define FALSE 0
 32 
 33 /* lcd 操作相关 头文件 */
 34 #include <sys/types.h>
 35 #include <sys/stat.h>
 36 #include <fcntl.h>
 37 #include <linux/fb.h>
 38 #include <sys/ioctl.h>
 39 #include <unistd.h>
 40 #include <string.h>
 41 #include <sys/mman.h>
 42 
 43 static int fb_fd;
 44 static unsigned char *fb_mem;
 45 static int px_width;
 46 static int line_width;
 47 static int screen_width;
 48 static struct fb_var_screeninfo var;
 49 
 50 static int lcd_fb_display_px(WORD color, int x, int y)
 51 {
 52     unsigned char  *pen8;
 53     unsigned short *pen16;
 54     
 55     pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
 56     pen16 = (unsigned short *)pen8;
 57     *pen16 = color;
 58     
 59     return 0;
 60 }
 61 
 62 static int lcd_fb_init()
 63 {
 64     //如果使用 mmap 打开方式 必须是 读定方式
 65     fb_fd = open("/dev/fb0", O_RDWR);
 66     if(-1 == fb_fd)
 67     {
 68         printf("cat't open /dev/fb0 \n");
 69         return -1;
 70     }
 71     //获取屏幕参数
 72     if(-1 == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
 73     {
 74         close(fb_fd);
 75         printf("cat't ioctl /dev/fb0 \n");
 76         return -1;
 77     }
 78     
 79     //计算参数
 80     px_width = var.bits_per_pixel / 8;
 81     line_width = var.xres * px_width;
 82     screen_width = var.yres * line_width;
 83     
 84     fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
 85     if(fb_mem == (void *)-1)
 86     {
 87         close(fb_fd);
 88         printf("cat't mmap /dev/fb0 \n");
 89         return -1;
 90     }
 91     //清屏
 92     memset(fb_mem, 0 , screen_width);
 93     return 0;
 94 }
 95 
 96 /*-------------------------------------------------------------------*/
 97 /*  ROM image file information                                       */
 98 /*-------------------------------------------------------------------*/
 99 
100 char    szRomName[256];
101 char    szSaveName[256];
102 int    nSRAM_SaveFlag;
103 
104 /*-------------------------------------------------------------------*/
105 /*  Constants ( Linux specific )                                     */
106 /*-------------------------------------------------------------------*/
107 
108 #define VBOX_SIZE    7
109 #define SOUND_DEVICE    "/dev/dsp"
110 #define VERSION        "InfoNES v0.91J"
111 
112 /*-------------------------------------------------------------------*/
113 /*  Global Variables ( Linux specific )                              */
114 /*-------------------------------------------------------------------*/
115 
116 /* Emulation thread */
117 pthread_t  emulation_tid;
118 int bThread;
119 
120 /* Pad state */
121 DWORD    dwKeyPad1;
122 DWORD    dwKeyPad2;
123 DWORD    dwKeySystem;
124 
125 /* For Sound Emulation */
126 BYTE    final_wave[2048];
127 int    waveptr;
128 int    wavflag;
129 int    sound_fd;
130 
131 /*-------------------------------------------------------------------*/
132 /*  Function prototypes ( Linux specific )                           */
133 /*-------------------------------------------------------------------*/
134 
135 void *emulation_thread( void *args );
136 
137 
138 void start_application( char *filename );
139 
140 
141 int LoadSRAM();
142 
143 
144 int SaveSRAM();
145 
146 
147 /* Palette data */
148 WORD NesPalette[64] =
149 {
150     0x39ce, 0x1071, 0x0015, 0x2013, 0x440e, 0x5402, 0x5000, 0x3c20,
151     0x20a0, 0x0100, 0x0140, 0x00e2, 0x0ceb, 0x0000, 0x0000, 0x0000,
152     0x5ef7, 0x01dd, 0x10fd, 0x401e, 0x5c17, 0x700b, 0x6ca0, 0x6521,
153     0x45c0, 0x0240, 0x02a0, 0x0247, 0x0211, 0x0000, 0x0000, 0x0000,
154     0x7fff, 0x1eff, 0x2e5f, 0x223f, 0x79ff, 0x7dd6, 0x7dcc, 0x7e67,
155     0x7ae7, 0x4342, 0x2769, 0x2ff3, 0x03bb, 0x0000, 0x0000, 0x0000,
156     0x7fff, 0x579f, 0x635f, 0x6b3f, 0x7f1f, 0x7f1b, 0x7ef6, 0x7f75,
157     0x7f94, 0x73f4, 0x57d7, 0x5bf9, 0x4ffe, 0x0000, 0x0000, 0x0000
158 };
159 
160 /*===================================================================*/
161 /*                                                                   */
162 /*                main() : Application main                          */
163 /*                                                                   */
164 /*===================================================================*/
165 
166 /* Application main */
167 int main( int argc, char **argv )
168 {
169     int i;
170 
171     /*-------------------------------------------------------------------*/
172     /*  Pad Control                                                      */
173     /*-------------------------------------------------------------------*/
174 
175     /* Initialize a pad state */
176     dwKeyPad1    = 0;
177     dwKeyPad2    = 0;
178     dwKeySystem = 0;
179 
180     /*-------------------------------------------------------------------*/
181     /*  Load Cassette & Create Thread                                    */
182     /*-------------------------------------------------------------------*/
183 
184     /* Initialize thread state */
185     bThread = FALSE;
186 
187     /* If a rom name specified, start it */
188     if ( argc == 2 )
189     {
190         start_application( argv[1] );
191     }
192     
193     lcd_fb_init();
194     
195     //主循环不要让程序退出
196     while(1)
197     {
198         
199     }
200     return(0);
201 }
202 
203 
204 /*===================================================================*/
205 /*                                                                   */
206 /*           emulation_thread() : Thread Hooking Routine             */
207 /*                                                                   */
208 /*===================================================================*/
209 
210 void *emulation_thread( void *args )
211 {
212     InfoNES_Main();
213 }
214 
215 
216 /*===================================================================*/
217 /*                                                                   */
218 /*     start_application() : Start NES Hardware                      */
219 /*                                                                   */
220 /*===================================================================*/
221 void start_application( char *filename )
222 {
223     /* Set a ROM image name */
224     strcpy( szRomName, filename );
225 
226     /* Load cassette */
227     if ( InfoNES_Load( szRomName ) == 0 )
228     {
229         /* Load SRAM */
230         LoadSRAM();
231 
232         /* Create Emulation Thread */
233         bThread = TRUE;
234         pthread_create( &emulation_tid, NULL, emulation_thread, NULL );
235     }
236 }
237 
238 
239 /*===================================================================*/
240 /*                                                                   */
241 /*           LoadSRAM() : Load a SRAM                                */
242 /*                                                                   */
243 /*===================================================================*/
244 int LoadSRAM()
245 {
246 /*
247  *  Load a SRAM
248  *
249  *  Return values
250  *     0 : Normally
251  *    -1 : SRAM data couldn't be read
252  */
253 
254     FILE        *fp;
255     unsigned char    pSrcBuf[SRAM_SIZE];
256     unsigned char    chData;
257     unsigned char    chTag;
258     int        nRunLen;
259     int        nDecoded;
260     int        nDecLen;
261     int        nIdx;
262 
263     /* It doesn't need to save it */
264     nSRAM_SaveFlag = 0;
265 
266     /* It is finished if the ROM doesn't have SRAM */
267     if ( !ROM_SRAM )
268         return(0);
269 
270     /* There is necessity to save it */
271     nSRAM_SaveFlag = 1;
272 
273     /* The preparation of the SRAM file name */
274     strcpy( szSaveName, szRomName );
275     strcpy( strrchr( szSaveName, '.' ) + 1, "srm" );
276 
277     /*-------------------------------------------------------------------*/
278     /*  Read a SRAM data                                                 */
279     /*-------------------------------------------------------------------*/
280 
281     /* Open SRAM file */
282     fp = fopen( szSaveName, "rb" );
283     if ( fp == NULL )
284         return(-1);
285 
286     /* Read SRAM data */
287     fread( pSrcBuf, SRAM_SIZE, 1, fp );
288 
289     /* Close SRAM file */
290     fclose( fp );
291 
292     /*-------------------------------------------------------------------*/
293     /*  Extract a SRAM data                                              */
294     /*-------------------------------------------------------------------*/
295 
296     nDecoded    = 0;
297     nDecLen        = 0;
298 
299     chTag = pSrcBuf[nDecoded++];
300 
301     while ( nDecLen < 8192 )
302     {
303         chData = pSrcBuf[nDecoded++];
304 
305         if ( chData == chTag )
306         {
307             chData    = pSrcBuf[nDecoded++];
308             nRunLen = pSrcBuf[nDecoded++];
309             for ( nIdx = 0; nIdx < nRunLen + 1; ++nIdx )
310             {
311                 SRAM[nDecLen++] = chData;
312             }
313         }else  {
314             SRAM[nDecLen++] = chData;
315         }
316     }
317 
318     /* Successful */
319     return(0);
320 }
321 
322 
323 /*===================================================================*/
324 /*                                                                   */
325 /*           SaveSRAM() : Save a SRAM                                */
326 /*                                                                   */
327 /*===================================================================*/
328 int SaveSRAM()
329 {
330 /*
331  *  Save a SRAM
332  *
333  *  Return values
334  *     0 : Normally
335  *    -1 : SRAM data couldn't be written
336  */
337 
338     FILE        *fp;
339     int        nUsedTable[256];
340     unsigned char    chData;
341     unsigned char    chPrevData;
342     unsigned char    chTag;
343     int        nIdx;
344     int        nEncoded;
345     int        nEncLen;
346     int        nRunLen;
347     unsigned char    pDstBuf[SRAM_SIZE];
348 
349     if ( !nSRAM_SaveFlag )
350         return(0);  /* It doesn't need to save it */
351 
352     /*-------------------------------------------------------------------*/
353     /*  Compress a SRAM data                                             */
354     /*-------------------------------------------------------------------*/
355 
356     memset( nUsedTable, 0, sizeof nUsedTable );
357 
358     for ( nIdx = 0; nIdx < SRAM_SIZE; ++nIdx )
359     {
360         ++nUsedTable[SRAM[nIdx++]];
361     }
362     for ( nIdx = 1, chTag = 0; nIdx < 256; ++nIdx )
363     {
364         if ( nUsedTable[nIdx] < nUsedTable[chTag] )
365             chTag = nIdx;
366     }
367 
368     nEncoded    = 0;
369     nEncLen        = 0;
370     nRunLen        = 1;
371 
372     pDstBuf[nEncLen++] = chTag;
373 
374     chPrevData = SRAM[nEncoded++];
375 
376     while ( nEncoded < SRAM_SIZE && nEncLen < SRAM_SIZE - 133 )
377     {
378         chData = SRAM[nEncoded++];
379 
380         if ( chPrevData == chData && nRunLen < 256 )
381             ++nRunLen;
382         else{
383             if ( nRunLen >= 4 || chPrevData == chTag )
384             {
385                 pDstBuf[nEncLen++]    = chTag;
386                 pDstBuf[nEncLen++]    = chPrevData;
387                 pDstBuf[nEncLen++]    = nRunLen - 1;
388             }else  {
389                 for ( nIdx = 0; nIdx < nRunLen; ++nIdx )
390                     pDstBuf[nEncLen++] = chPrevData;
391             }
392 
393             chPrevData    = chData;
394             nRunLen        = 1;
395         }
396     }
397     if ( nRunLen >= 4 || chPrevData == chTag )
398     {
399         pDstBuf[nEncLen++]    = chTag;
400         pDstBuf[nEncLen++]    = chPrevData;
401         pDstBuf[nEncLen++]    = nRunLen - 1;
402     }else  {
403         for ( nIdx = 0; nIdx < nRunLen; ++nIdx )
404             pDstBuf[nEncLen++] = chPrevData;
405     }
406 
407     /*-------------------------------------------------------------------*/
408     /*  Write a SRAM data                                                */
409     /*-------------------------------------------------------------------*/
410 
411     /* Open SRAM file */
412     fp = fopen( szSaveName, "wb" );
413     if ( fp == NULL )
414         return(-1);
415 
416     /* Write SRAM data */
417     fwrite( pDstBuf, nEncLen, 1, fp );
418 
419     /* Close SRAM file */
420     fclose( fp );
421 
422     /* Successful */
423     return(0);
424 }
425 
426 
427 /*===================================================================*/
428 /*                                                                   */
429 /*                  InfoNES_Menu() : Menu screen                     */
430 /*                                                                   */
431 /*===================================================================*/
432 int InfoNES_Menu()
433 {
434 /*
435  *  Menu screen
436  *
437  *  Return values
438  *     0 : Normally
439  *    -1 : Exit InfoNES
440  */
441 
442     /* If terminated */
443     if ( bThread == FALSE )
444     {
445         return(-1);
446     }
447 
448     /* Nothing to do here */
449     return(0);
450 }
451 
452 
453 /*===================================================================*/
454 /*                                                                   */
455 /*               InfoNES_ReadRom() : Read ROM image file             */
456 /*                                                                   */
457 /*===================================================================*/
458 int InfoNES_ReadRom( const char *pszFileName )
459 {
460 /*
461  *  Read ROM image file
462  *
463  *  Parameters
464  *    const char *pszFileName          (Read)
465  *
466  *  Return values
467  *     0 : Normally
468  *    -1 : Error
469  */
470 
471     FILE *fp;
472 
473     /* Open ROM file */
474     fp = fopen( pszFileName, "rb" );
475     if ( fp == NULL )
476         return(-1);
477 
478     /* Read ROM Header */
479     fread( &NesHeader, sizeof NesHeader, 1, fp );
480     if ( memcmp( NesHeader.byID, "NES\x1a", 4 ) != 0 )
481     {
482         /* not .nes file */
483         fclose( fp );
484         return(-1);
485     }
486 
487     /* Clear SRAM */
488     memset( SRAM, 0, SRAM_SIZE );
489 
490     /* If trainer presents Read Triner at 0x7000-0x71ff */
491     if ( NesHeader.byInfo1 & 4 )
492     {
493         fread( &SRAM[0x1000], 512, 1, fp );
494     }
495 
496     /* Allocate Memory for ROM Image */
497     ROM = (BYTE *) malloc( NesHeader.byRomSize * 0x4000 );
498 
499     /* Read ROM Image */
500     fread( ROM, 0x4000, NesHeader.byRomSize, fp );
501 
502     if ( NesHeader.byVRomSize > 0 )
503     {
504         /* Allocate Memory for VROM Image */
505         VROM = (BYTE *) malloc( NesHeader.byVRomSize * 0x2000 );
506 
507         /* Read VROM Image */
508         fread( VROM, 0x2000, NesHeader.byVRomSize, fp );
509     }
510 
511     /* File close */
512     fclose( fp );
513 
514     /* Successful */
515     return(0);
516 }
517 
518 
519 /*===================================================================*/
520 /*                                                                   */
521 /*           InfoNES_ReleaseRom() : Release a memory for ROM         */
522 /*                                                                   */
523 /*===================================================================*/
524 void InfoNES_ReleaseRom()
525 {
526 /*
527  *  Release a memory for ROM
528  *
529  */
530 
531     if ( ROM )
532     {
533         free( ROM );
534         ROM = NULL;
535     }
536 
537     if ( VROM )
538     {
539         free( VROM );
540         VROM = NULL;
541     }
542 }
543 
544 
545 /*===================================================================*/
546 /*                                                                   */
547 /*             InfoNES_MemoryCopy() : memcpy                         */
548 /*                                                                   */
549 /*===================================================================*/
550 void *InfoNES_MemoryCopy( void *dest, const void *src, int count )
551 {
552 /*
553  *  memcpy
554  *
555  *  Parameters
556  *    void *dest                       (Write)
557  *      Points to the starting address of the copied block's destination
558  *
559  *    const void *src                  (Read)
560  *      Points to the starting address of the block of memory to copy
561  *
562  *    int count                        (Read)
563  *      Specifies the size, in bytes, of the block of memory to copy
564  *
565  *  Return values
566  *    Pointer of destination
567  */
568 
569     memcpy( dest, src, count );
570     return(dest);
571 }
572 
573 
574 /*===================================================================*/
575 /*                                                                   */
576 /*             InfoNES_MemorySet() : memset                          */
577 /*                                                                   */
578 /*===================================================================*/
579 void *InfoNES_MemorySet( void *dest, int c, int count )
580 {
581 /*
582  *  memset
583  *
584  *  Parameters
585  *    void *dest                       (Write)
586  *      Points to the starting address of the block of memory to fill
587  *
588  *    int c                            (Read)
589  *      Specifies the byte value with which to fill the memory block
590  *
591  *    int count                        (Read)
592  *      Specifies the size, in bytes, of the block of memory to fill
593  *
594  *  Return values
595  *    Pointer of destination
596  */
597 
598     memset( dest, c, count );
599     return(dest);
600 }
601 
602 
603 /*===================================================================*/
604 /*                                                                   */
605 /*      InfoNES_LoadFrame() :                                        */
606 /*           Transfer the contents of work frame on the screen       */
607 /*                                                                   */
608 /*===================================================================*/
609 void InfoNES_LoadFrame()
610 {
611     int x,y;
612     WORD wColor;
613     for (y = 0; y < NES_DISP_HEIGHT; y++ )
614     {
615         for (x = 0; x < NES_DISP_WIDTH; x++ )
616         {
617             wColor = WorkFrame[y * NES_DISP_WIDTH  + x ];
618             lcd_fb_display_px(wColor, x, y);
619         }
620     }
621 }
622 
623 
624 /*===================================================================*/
625 /*                                                                   */
626 /*             InfoNES_PadState() : Get a joypad state               */
627 /*                                                                   */
628 /*===================================================================*/
629 void InfoNES_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem )
630 {
631 /*
632  *  Get a joypad state
633  *
634  *  Parameters
635  *    DWORD *pdwPad1                   (Write)
636  *      Joypad 1 State
637  *
638  *    DWORD *pdwPad2                   (Write)
639  *      Joypad 2 State
640  *
641  *    DWORD *pdwSystem                 (Write)
642  *      Input for InfoNES
643  *
644  */
645 
646     /* Transfer joypad state */
647     *pdwPad1    = dwKeyPad1;
648     *pdwPad2    = dwKeyPad2;
649     *pdwSystem    = dwKeySystem;
650 }
651 
652 
653 /*===================================================================*/
654 /*                                                                   */
655 /*        InfoNES_SoundInit() : Sound Emulation Initialize           */
656 /*                                                                   */
657 /*===================================================================*/
658 void InfoNES_SoundInit( void )
659 {
660     sound_fd = 0;
661 }
662 
663 
664 /*===================================================================*/
665 /*                                                                   */
666 /*        InfoNES_SoundOpen() : Sound Open                           */
667 /*                                                                   */
668 /*===================================================================*/
669 int InfoNES_SoundOpen( int samples_per_sync, int sample_rate )
670 {
671     return 1;
672 }
673 
674 
675 /*===================================================================*/
676 /*                                                                   */
677 /*        InfoNES_SoundClose() : Sound Close                         */
678 /*                                                                   */
679 /*===================================================================*/
680 void InfoNES_SoundClose( void )
681 {
682     if ( sound_fd )
683     {
684         close( sound_fd );
685     }
686 }
687 
688 
689 /*===================================================================*/
690 /*                                                                   */
691 /*            InfoNES_SoundOutput() : Sound Output 5 Waves           */
692 /*                                                                   */
693 /*===================================================================*/
694 void InfoNES_SoundOutput( int samples, BYTE *wave1, BYTE *wave2, BYTE *wave3, BYTE *wave4, BYTE *wave5 )
695 {
696     
697 }
698 
699 
700 /*===================================================================*/
701 /*                                                                   */
702 /*            InfoNES_Wait() : Wait Emulation if required            */
703 /*                                                                   */
704 /*===================================================================*/
705 void InfoNES_Wait()
706 {
707 }
708 
709 
710 /*===================================================================*/
711 /*                                                                   */
712 /*            InfoNES_MessageBox() : Print System Message            */
713 /*                                                                   */
714 /*===================================================================*/
715 void InfoNES_MessageBox( char *pszMsg, ... )
716 {
717     printf( "MessageBox: %s \n", pszMsg );
718 }
719 
720 
721 /*
722  * End of InfoNES_System_Linux.cpp
723  */

Makefile

 1 CC = arm-linux-gcc
 2 TARBALL = InfoNES08J
 3 
 4 # InfoNES
 5 .CFILES =    ./../K6502.cpp \
 6         ./../InfoNES.cpp \
 7         ./../InfoNES_Mapper.cpp \
 8         ./../InfoNES_pAPU.cpp \
 9         ./InfoNES_System_Linux.cpp
10 
11 .OFILES    =    $(.CFILES:.cpp=.o)
12 
13 CCFLAGS =  -O2 -fsigned-char 
14 LDFILGS = -lstdc++        # gcc3.x.x
15 
16 all: InfoNES
17 
18 InfoNES: $(.OFILES)
19     $(CC) $(INCLUDES) -o $@ $(.OFILES) $(LDFILGS) -lm -lz -lpthread
20 
21 .cpp.o:
22     $(CC) $(INCLUDES) -c $(CCFLAGS) $*.cpp  -o $@
23 
24 clean:
25     rm -f $(.OFILES) ../*~ ../*/*~ core
26 
27 cleanall:
28     rm -f $(.OFILES) ../*~ ../*/*~ core InfoNES
29 
30 release: clean all
31 
32 tar:
33     ( cd ..; \
34     tar cvf $(TARBALL).tar ./*; \
35     gzip $(TARBALL).tar \
36     )
37 
38 install:
39     install ./InfoNES /usr/local/bin

 

posted @ 2016-06-27 15:15  宁次  阅读(4040)  评论(0编辑  收藏  举报