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 }