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
/*===================================================================*/
/* */
/* InfoNES_System_Linux.cpp : Linux specific File */
/* */
/* 2001/05/18 InfoNES Project ( Sound is based on DarcNES ) */
/* */
/*===================================================================*/ /*-------------------------------------------------------------------*/
/* Include files */
/*-------------------------------------------------------------------*/ #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h> #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/soundcard.h> #include "../InfoNES.h"
#include "../InfoNES_System.h"
#include "../InfoNES_pAPU.h" //bool define
#define TRUE 1
#define FALSE 0 /* lcd 操作相关 头文件 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h> static int fb_fd;
static unsigned char *fb_mem;
static int px_width;
static int line_width;
static int screen_width;
static struct fb_var_screeninfo var; static int lcd_fb_display_px(WORD color, int x, int y)
{
unsigned char *pen8;
unsigned short *pen16; pen8 = (unsigned char *)(fb_mem + y*line_width + x*px_width);
pen16 = (unsigned short *)pen8;
*pen16 = color; return ;
} static int lcd_fb_init()
{
//如果使用 mmap 打开方式 必须是 读定方式
fb_fd = open("/dev/fb0", O_RDWR);
if(- == fb_fd)
{
printf("cat't open /dev/fb0 \n");
return -;
}
//获取屏幕参数
if(- == ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
{
close(fb_fd);
printf("cat't ioctl /dev/fb0 \n");
return -;
} //计算参数
px_width = var.bits_per_pixel / ;
line_width = var.xres * px_width;
screen_width = var.yres * line_width; fb_mem = (unsigned char *)mmap(NULL, screen_width, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, );
if(fb_mem == (void *)-)
{
close(fb_fd);
printf("cat't mmap /dev/fb0 \n");
return -;
}
//清屏
memset(fb_mem, , screen_width);
return ;
} /*-------------------------------------------------------------------*/
/* ROM image file information */
/*-------------------------------------------------------------------*/ char szRomName[];
char szSaveName[];
int nSRAM_SaveFlag; /*-------------------------------------------------------------------*/
/* Constants ( Linux specific ) */
/*-------------------------------------------------------------------*/ #define VBOX_SIZE 7
#define SOUND_DEVICE "/dev/dsp"
#define VERSION "InfoNES v0.91J" /*-------------------------------------------------------------------*/
/* Global Variables ( Linux specific ) */
/*-------------------------------------------------------------------*/ /* Emulation thread */
pthread_t emulation_tid;
int bThread; /* Pad state */
DWORD dwKeyPad1;
DWORD dwKeyPad2;
DWORD dwKeySystem; /* For Sound Emulation */
BYTE final_wave[];
int waveptr;
int wavflag;
int sound_fd; /*-------------------------------------------------------------------*/
/* Function prototypes ( Linux specific ) */
/*-------------------------------------------------------------------*/ void *emulation_thread( void *args ); void start_application( char *filename ); int LoadSRAM(); int SaveSRAM(); /* Palette data */
WORD NesPalette[] =
{
0x39ce, 0x1071, 0x0015, 0x2013, 0x440e, 0x5402, 0x5000, 0x3c20,
0x20a0, 0x0100, 0x0140, 0x00e2, 0x0ceb, 0x0000, 0x0000, 0x0000,
0x5ef7, 0x01dd, 0x10fd, 0x401e, 0x5c17, 0x700b, 0x6ca0, 0x6521,
0x45c0, 0x0240, 0x02a0, 0x0247, 0x0211, 0x0000, 0x0000, 0x0000,
0x7fff, 0x1eff, 0x2e5f, 0x223f, 0x79ff, 0x7dd6, 0x7dcc, 0x7e67,
0x7ae7, 0x4342, 0x2769, 0x2ff3, 0x03bb, 0x0000, 0x0000, 0x0000,
0x7fff, 0x579f, 0x635f, 0x6b3f, 0x7f1f, 0x7f1b, 0x7ef6, 0x7f75,
0x7f94, 0x73f4, 0x57d7, 0x5bf9, 0x4ffe, 0x0000, 0x0000, 0x0000
}; /*===================================================================*/
/* */
/* main() : Application main */
/* */
/*===================================================================*/ /* Application main */
int main( int argc, char **argv )
{
int i; /*-------------------------------------------------------------------*/
/* Pad Control */
/*-------------------------------------------------------------------*/ /* Initialize a pad state */
dwKeyPad1 = ;
dwKeyPad2 = ;
dwKeySystem = ; /*-------------------------------------------------------------------*/
/* Load Cassette & Create Thread */
/*-------------------------------------------------------------------*/ /* Initialize thread state */
bThread = FALSE; /* If a rom name specified, start it */
if ( argc == )
{
start_application( argv[] );
} lcd_fb_init(); //主循环不要让程序退出
while()
{ }
return();
} /*===================================================================*/
/* */
/* emulation_thread() : Thread Hooking Routine */
/* */
/*===================================================================*/ void *emulation_thread( void *args )
{
InfoNES_Main();
} /*===================================================================*/
/* */
/* start_application() : Start NES Hardware */
/* */
/*===================================================================*/
void start_application( char *filename )
{
/* Set a ROM image name */
strcpy( szRomName, filename ); /* Load cassette */
if ( InfoNES_Load( szRomName ) == )
{
/* Load SRAM */
LoadSRAM(); /* Create Emulation Thread */
bThread = TRUE;
pthread_create( &emulation_tid, NULL, emulation_thread, NULL );
}
} /*===================================================================*/
/* */
/* LoadSRAM() : Load a SRAM */
/* */
/*===================================================================*/
int LoadSRAM()
{
/*
* Load a SRAM
*
* Return values
* 0 : Normally
* -1 : SRAM data couldn't be read
*/ FILE *fp;
unsigned char pSrcBuf[SRAM_SIZE];
unsigned char chData;
unsigned char chTag;
int nRunLen;
int nDecoded;
int nDecLen;
int nIdx; /* It doesn't need to save it */
nSRAM_SaveFlag = ; /* It is finished if the ROM doesn't have SRAM */
if ( !ROM_SRAM )
return(); /* There is necessity to save it */
nSRAM_SaveFlag = ; /* The preparation of the SRAM file name */
strcpy( szSaveName, szRomName );
strcpy( strrchr( szSaveName, '.' ) + , "srm" ); /*-------------------------------------------------------------------*/
/* Read a SRAM data */
/*-------------------------------------------------------------------*/ /* Open SRAM file */
fp = fopen( szSaveName, "rb" );
if ( fp == NULL )
return(-); /* Read SRAM data */
fread( pSrcBuf, SRAM_SIZE, , fp ); /* Close SRAM file */
fclose( fp ); /*-------------------------------------------------------------------*/
/* Extract a SRAM data */
/*-------------------------------------------------------------------*/ nDecoded = ;
nDecLen = ; chTag = pSrcBuf[nDecoded++]; while ( nDecLen < )
{
chData = pSrcBuf[nDecoded++]; if ( chData == chTag )
{
chData = pSrcBuf[nDecoded++];
nRunLen = pSrcBuf[nDecoded++];
for ( nIdx = ; nIdx < nRunLen + ; ++nIdx )
{
SRAM[nDecLen++] = chData;
}
}else {
SRAM[nDecLen++] = chData;
}
} /* Successful */
return();
} /*===================================================================*/
/* */
/* SaveSRAM() : Save a SRAM */
/* */
/*===================================================================*/
int SaveSRAM()
{
/*
* Save a SRAM
*
* Return values
* 0 : Normally
* -1 : SRAM data couldn't be written
*/ FILE *fp;
int nUsedTable[];
unsigned char chData;
unsigned char chPrevData;
unsigned char chTag;
int nIdx;
int nEncoded;
int nEncLen;
int nRunLen;
unsigned char pDstBuf[SRAM_SIZE]; if ( !nSRAM_SaveFlag )
return(); /* It doesn't need to save it */ /*-------------------------------------------------------------------*/
/* Compress a SRAM data */
/*-------------------------------------------------------------------*/ memset( nUsedTable, , sizeof nUsedTable ); for ( nIdx = ; nIdx < SRAM_SIZE; ++nIdx )
{
++nUsedTable[SRAM[nIdx++]];
}
for ( nIdx = , chTag = ; nIdx < ; ++nIdx )
{
if ( nUsedTable[nIdx] < nUsedTable[chTag] )
chTag = nIdx;
} nEncoded = ;
nEncLen = ;
nRunLen = ; pDstBuf[nEncLen++] = chTag; chPrevData = SRAM[nEncoded++]; while ( nEncoded < SRAM_SIZE && nEncLen < SRAM_SIZE - )
{
chData = SRAM[nEncoded++]; if ( chPrevData == chData && nRunLen < )
++nRunLen;
else{
if ( nRunLen >= || chPrevData == chTag )
{
pDstBuf[nEncLen++] = chTag;
pDstBuf[nEncLen++] = chPrevData;
pDstBuf[nEncLen++] = nRunLen - ;
}else {
for ( nIdx = ; nIdx < nRunLen; ++nIdx )
pDstBuf[nEncLen++] = chPrevData;
} chPrevData = chData;
nRunLen = ;
}
}
if ( nRunLen >= || chPrevData == chTag )
{
pDstBuf[nEncLen++] = chTag;
pDstBuf[nEncLen++] = chPrevData;
pDstBuf[nEncLen++] = nRunLen - ;
}else {
for ( nIdx = ; nIdx < nRunLen; ++nIdx )
pDstBuf[nEncLen++] = chPrevData;
} /*-------------------------------------------------------------------*/
/* Write a SRAM data */
/*-------------------------------------------------------------------*/ /* Open SRAM file */
fp = fopen( szSaveName, "wb" );
if ( fp == NULL )
return(-); /* Write SRAM data */
fwrite( pDstBuf, nEncLen, , fp ); /* Close SRAM file */
fclose( fp ); /* Successful */
return();
} /*===================================================================*/
/* */
/* InfoNES_Menu() : Menu screen */
/* */
/*===================================================================*/
int InfoNES_Menu()
{
/*
* Menu screen
*
* Return values
* 0 : Normally
* -1 : Exit InfoNES
*/ /* If terminated */
if ( bThread == FALSE )
{
return(-);
} /* Nothing to do here */
return();
} /*===================================================================*/
/* */
/* InfoNES_ReadRom() : Read ROM image file */
/* */
/*===================================================================*/
int InfoNES_ReadRom( const char *pszFileName )
{
/*
* Read ROM image file
*
* Parameters
* const char *pszFileName (Read)
*
* Return values
* 0 : Normally
* -1 : Error
*/ FILE *fp; /* Open ROM file */
fp = fopen( pszFileName, "rb" );
if ( fp == NULL )
return(-); /* Read ROM Header */
fread( &NesHeader, sizeof NesHeader, , fp );
if ( memcmp( NesHeader.byID, "NES\x1a", ) != )
{
/* not .nes file */
fclose( fp );
return(-);
} /* Clear SRAM */
memset( SRAM, , SRAM_SIZE ); /* If trainer presents Read Triner at 0x7000-0x71ff */
if ( NesHeader.byInfo1 & )
{
fread( &SRAM[0x1000], , , fp );
} /* Allocate Memory for ROM Image */
ROM = (BYTE *) malloc( NesHeader.byRomSize * 0x4000 ); /* Read ROM Image */
fread( ROM, 0x4000, NesHeader.byRomSize, fp ); if ( NesHeader.byVRomSize > )
{
/* Allocate Memory for VROM Image */
VROM = (BYTE *) malloc( NesHeader.byVRomSize * 0x2000 ); /* Read VROM Image */
fread( VROM, 0x2000, NesHeader.byVRomSize, fp );
} /* File close */
fclose( fp ); /* Successful */
return();
} /*===================================================================*/
/* */
/* InfoNES_ReleaseRom() : Release a memory for ROM */
/* */
/*===================================================================*/
void InfoNES_ReleaseRom()
{
/*
* Release a memory for ROM
*
*/ if ( ROM )
{
free( ROM );
ROM = NULL;
} if ( VROM )
{
free( VROM );
VROM = NULL;
}
} /*===================================================================*/
/* */
/* InfoNES_MemoryCopy() : memcpy */
/* */
/*===================================================================*/
void *InfoNES_MemoryCopy( void *dest, const void *src, int count )
{
/*
* memcpy
*
* Parameters
* void *dest (Write)
* Points to the starting address of the copied block's destination
*
* const void *src (Read)
* Points to the starting address of the block of memory to copy
*
* int count (Read)
* Specifies the size, in bytes, of the block of memory to copy
*
* Return values
* Pointer of destination
*/ memcpy( dest, src, count );
return(dest);
} /*===================================================================*/
/* */
/* InfoNES_MemorySet() : memset */
/* */
/*===================================================================*/
void *InfoNES_MemorySet( void *dest, int c, int count )
{
/*
* memset
*
* Parameters
* void *dest (Write)
* Points to the starting address of the block of memory to fill
*
* int c (Read)
* Specifies the byte value with which to fill the memory block
*
* int count (Read)
* Specifies the size, in bytes, of the block of memory to fill
*
* Return values
* Pointer of destination
*/ memset( dest, c, count );
return(dest);
} /*===================================================================*/
/* */
/* InfoNES_LoadFrame() : */
/* Transfer the contents of work frame on the screen */
/* */
/*===================================================================*/
void InfoNES_LoadFrame()
{
int x,y;
WORD wColor;
for (y = ; y < NES_DISP_HEIGHT; y++ )
{
for (x = ; x < NES_DISP_WIDTH; x++ )
{
wColor = WorkFrame[y * NES_DISP_WIDTH + x ];
lcd_fb_display_px(wColor, x, y);
}
}
} /*===================================================================*/
/* */
/* InfoNES_PadState() : Get a joypad state */
/* */
/*===================================================================*/
void InfoNES_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem )
{
/*
* Get a joypad state
*
* Parameters
* DWORD *pdwPad1 (Write)
* Joypad 1 State
*
* DWORD *pdwPad2 (Write)
* Joypad 2 State
*
* DWORD *pdwSystem (Write)
* Input for InfoNES
*
*/ /* Transfer joypad state */
*pdwPad1 = dwKeyPad1;
*pdwPad2 = dwKeyPad2;
*pdwSystem = dwKeySystem;
} /*===================================================================*/
/* */
/* InfoNES_SoundInit() : Sound Emulation Initialize */
/* */
/*===================================================================*/
void InfoNES_SoundInit( void )
{
sound_fd = ;
} /*===================================================================*/
/* */
/* InfoNES_SoundOpen() : Sound Open */
/* */
/*===================================================================*/
int InfoNES_SoundOpen( int samples_per_sync, int sample_rate )
{
return ;
} /*===================================================================*/
/* */
/* InfoNES_SoundClose() : Sound Close */
/* */
/*===================================================================*/
void InfoNES_SoundClose( void )
{
if ( sound_fd )
{
close( sound_fd );
}
} /*===================================================================*/
/* */
/* InfoNES_SoundOutput() : Sound Output 5 Waves */
/* */
/*===================================================================*/
void InfoNES_SoundOutput( int samples, BYTE *wave1, BYTE *wave2, BYTE *wave3, BYTE *wave4, BYTE *wave5 )
{ } /*===================================================================*/
/* */
/* InfoNES_Wait() : Wait Emulation if required */
/* */
/*===================================================================*/
void InfoNES_Wait()
{
} /*===================================================================*/
/* */
/* InfoNES_MessageBox() : Print System Message */
/* */
/*===================================================================*/
void InfoNES_MessageBox( char *pszMsg, ... )
{
printf( "MessageBox: %s \n", pszMsg );
} /*
* End of InfoNES_System_Linux.cpp
*/
Makefile
CC = arm-linux-gcc
TARBALL = InfoNES08J # InfoNES
.CFILES = ./../K6502.cpp \
./../InfoNES.cpp \
./../InfoNES_Mapper.cpp \
./../InfoNES_pAPU.cpp \
./InfoNES_System_Linux.cpp .OFILES = $(.CFILES:.cpp=.o) CCFLAGS = -O2 -fsigned-char
LDFILGS = -lstdc++ # gcc3.x.x all: InfoNES InfoNES: $(.OFILES)
$(CC) $(INCLUDES) -o $@ $(.OFILES) $(LDFILGS) -lm -lz -lpthread .cpp.o:
$(CC) $(INCLUDES) -c $(CCFLAGS) $*.cpp -o $@ clean:
rm -f $(.OFILES) ../*~ ../*/*~ core cleanall:
rm -f $(.OFILES) ../*~ ../*/*~ core InfoNES release: clean all tar:
( cd ..; \
tar cvf $(TARBALL).tar ./*; \
gzip $(TARBALL).tar \
) install:
install ./InfoNES /usr/local/bin
nes 红白机模拟器 第2篇 InfoNES的更多相关文章
- arm 2440 linux 应用程序 nes 红白机模拟器 第2篇 InfoNES
InfoNES 支持 map ,声音,代码比较少,方便 移值. 在上个 LiteNES 的基础上,其实不到半小时就移值好了这个,但问题是,一直是黑屏.InfoNES_LoadFrame () Wo ...
- nes 红白机模拟器 第7篇 编译使用方法
模拟器,基于 InfoNES ,作者添加修改以下功能: 1, joypad 真实手柄驱动程序(字符型设备驱动) 2,原始图像只有256*240 ,添加 图像放大算法,这里实现了2种,a, 最近邻插值 ...
- arm 2440 linux 应用程序 nes 红白机模拟器 第1篇
对比了很多种,开源的 NES 模拟器 VirtuaNES , nestopia , FakeNES , FCEUX , InfoNES , LiteNES 最后决定使用 LiteNES 进行移值,它是 ...
- nes 红白机模拟器 第1篇
对比了很多种,开源的 NES 模拟器 VirtuaNES , nestopia , FakeNES , FCEUX , InfoNES , LiteNES 最后决定使用 LiteNES 进行移值,它是 ...
- arm 2440 linux 应用程序 nes 红白机模拟器 第4篇 linux 手柄驱动支持
小霸王学习机的真实手柄,实测CPU 占用 80% 接线图: 手柄读时序: joypad.c 驱动: 普通的字符设备驱动. #include <linux/module.h> #includ ...
- nes 红白机模拟器 第6篇 声音支持
InfoNES 源码中并没有包含 linux 的声音支持. 但提供 wince 和 win 的工程,文件,通过分析,win 的 DirectSound 发声,在使用 linux ALSA 实现. 先使 ...
- nes 红白机模拟器 第5篇 全屏显示
先看一下效果图 放大的原理是使用最初级的算法,直接取对应像素法. /*================================================================= ...
- nes 红白机模拟器 第4篇 linux 手柄驱动支持
小霸王学习机的真实手柄,实测CPU 占用 80% 接线图: 手柄读时序: joypad.c 驱动: 普通的字符设备驱动. #include <linux/module.h> #includ ...
- nes 红白机模拟器 第3篇 游戏手柄测试 51 STM32
手柄使用的是 CD4021 ,datasheet 上说支持 3V - 15V . 因为手柄是 5V 供电,2440 开发板上是GPIO 3.3V 电平,STM32 GPIO 也是 3.3V (也兼容5 ...
随机推荐
- 数论入门——斐蜀定理与拓展欧几里得算法
斐蜀定理 内容 斐蜀定理又叫贝祖定理,它的内容是这样的: 若$a,bin N$,那么对于任意x,y,方程$ax+by=gcd(a,b)*k(kin N)$一定有解,且一定有一组解使$ax+by=gcd ...
- VSAN磁盘扩容与收缩(二)
- iOS应用程序开发——解决iOS7之前版本与之后版本下app启动图片跳动问题
之前开发的app都是针对iOS6(兼容iOS5),所以在开发之初也出现了启动图片向下跳动的现象,通过网上的解决方法,代码中做了处理(“-20”): _imageView.frame = CGRectM ...
- 20180105关于课题所用的labview的改进随笔
在原有的工程上1.写入60个不同的数字~顶层,看测量次数是1.2.3.4.5.6.7.8.9的时候文件记到几次的数,一次的话,从接受命令到全部写到文件最短需要等多久.写入固定的数,通过startfla ...
- Nginx笔记总结九:Nginx日志配置
ngx_http_log_module用来定义请求日志格式1. access_log指令 语法: access_log path [format [buffer=size [flush=time] ...
- 浅谈javascript函数执行过程
javascript函数执行过程: 1. 为函数创建一个执行环境 2. 复制函数的 [[scopes]] 属性中的对象构建起执行环境的作用链域 3. 创建函数活动对象并推入执行环境作用链域的前端 4. ...
- bind(this)作用
.bind()创建了一个函数,当这个函数在被调用的时候,它的 this 关键词会被设置成被传入的值(这里指调用bind()时传入的参数
- Python如何让字典保持有序
问题: Python如何让字典保持有序 ? 解决方案: 使用collections.OrderedDict代替Dict. 验证程序: from collections import OrderedDi ...
- 餐厅随评系列之四:Umu日本料理(米其林二星)
文章目录 在过去的几个月,工作和生活都极其忙碌,因此博客短暂停更了一阵子.慢慢积累下了很多素材,从近期开始恢复博客更新,不过很多内容估计得靠回忆了. 索性采取"倒叙"的方法,先从最 ...
- WiFi产生电磁辐射或让人想去自杀
随着互联网在生活中的地位越来越重要,WiFi作为一种无线连接方式给了用户极大的便捷,然而有一部分科学家提出WiFi产生的电磁反应会对人的健康受到影响.面对这种说法,我们一直以为是专家在危言耸听,但是如 ...