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

先看一下效果图

 

放大的原理是使用最初级的算法,直接取对应像素法。

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

 

发另外一个高级点的放大算法 - 二次线性插值缩放算法

发算法核心部分,原理是,取原图相邻的4个橡素,算权重。 经过测试效率非常低(每秒一两帧的样子,当然也未做优化)

 1 //得到指定位置的像素颜色
 2 static int get_pixel(unsigned short *src_fb, int x, int y, int line_len, unsigned short *color)
 3 {
 4     int src_height = NES_DISP_HEIGHT;
 5     int src_width  = NES_DISP_WIDTH;
 6     if(y>src_height || x>src_width)
 7     {
 8         *color = 0;
 9         return 0;
10     }
11     *color = src_fb[line_len * y + x];
12 }
13 
14 static unsigned short color_avg(unsigned short color1, unsigned short color2, unsigned short color3, unsigned short color4)
15 {
16     unsigned short newColor;
17     unsigned int r,g,b;
18     //565
19     r = ((color1>>11)&0x1f + (color2>>11)&0x1f + (color3>>11)&0x1f + (color4>>11)&0x1f)/4;
20     g = ((color1>>5)&0x3f  + (color2>>5)&0x3f  + (color3>>5)&0x3f  + (color4>>5)&0x3f) /4;
21     b = ((color1>>0)&0x1f  + (color2>>0)&0x1f  + (color3>>0)&0x1f  + (color4>>0)&0x1f) /4;
22     newColor = ((r<<11) | (g<<5) | (b));
23     return newColor;
24 }
25 
26 //使用 二次线性插值 实现画面放大 
27 //说明 目前仅支持 16bpp 的LCD 显示 
28 //其它的还要修改兼容
29 static void lcd_draw()
30 {
31     int x;
32     int y;
33     float srcx;
34     float srcy;
35     int dst_y_line;
36     int src_height = NES_DISP_HEIGHT;
37     int src_width  = NES_DISP_WIDTH;
38     int dst_height = lcd_height;
39     int dst_width  = lcd_width;
40     unsigned short *src_fb = nes_disp_fb;
41     unsigned short *dst_fb = zoom_disp_fb;
42     int line_len = src_width;
43     
44     //Y坐标邻近的4个像素
45     unsigned short color1;
46     unsigned short color2;
47     unsigned short color3;
48     unsigned short color4;
49 
50     //算法说明
51     //1,取出目标XY坐标邻近的4个像素
52     for(y=0; y<dst_height; y++)
53     {
54         srcy = (y+0.49)*src_height/dst_height-0.5;
55         srcy = int(srcy);
56         dst_y_line = y*lcd_width;
57         for(x=0; x<dst_width; x++)
58         {
59             srcx = (x+0.49)*src_width/dst_width-0.5;
60             srcx = int(srcx);
61             get_pixel(src_fb, srcx,   srcy,   line_len, &color1);
62             get_pixel(src_fb, srcx,   srcy+1, line_len, &color2);
63             get_pixel(src_fb, srcx+1, srcy,   line_len, &color3);
64             get_pixel(src_fb, srcx+1, srcy+1, line_len, &color4);
65             //dst_fb[dst_y_line+x] = color_avg(color1, color2, color3, color4);
66             dst_fb[dst_y_line+x] = color1;
67         }
68     }
69     //复制到 fb
70     memcpy(fb_mem, dst_fb, screen_width);
71 }

 

posted @ 2017-04-24 10:36  宁次  阅读(2011)  评论(0编辑  收藏  举报