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 ...
随机推荐
- cannot be found on object of type xx.CacheExpressionRootObject
0 环境 系统环境:win10 编辑器:IDEA 1 前言->环境搭建 1-1 pom依赖 <?xml version="1.0" encoding="UTF ...
- dbSNP|n SwissVar|n CanProVar|CHPP|mutation assessor|
癌症蛋白质基因组学主要研究driver性质的突变,该突变有可能是转化为癌基因的突变.抑癌基因突变.药物位点突变和蛋白突变,可以使用mutation assessor 预测突变 突变导致疾病,修饰仅影响 ...
- C# Dictionary字典类介绍
说明 必须包含名空间System.Collection.Generic Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值) 键必须是唯一的,而值不需要唯 ...
- ServletContextListener 监听器
Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml文件配置好要 ...
- cashier|gasoline|reservoir
N-COUNT 出纳(员);收银员A cashier is a person who customers pay money to or get money from in places such a ...
- oracle存储过程随笔
有时间要把最近总结的存储过程的问题总结一下,先占坑: create or replace procedure test_proc2 as cursor cur is select YWR,YWRZJH ...
- Java发送Post请求,参数JSON,接收JSON
/** * 发送post请求 * @param url 路径 * @param jsonObject 参数(json类型) * @param encoding 编码格式 * @return * @th ...
- TCP/IP 协议栈初识
原文:深入浅出 TCP/IP 协议栈 0. 简介 TCP/IP 协议栈是网络通信中一系列网络协议的综合,是核心骨架.它定义了电子设备接入因特网.以及数据在它们之间的传输方式,是一份标准.TCP/IP ...
- php数据库连接和mysql语句使用
从简单的登录页开始学习. 前提:已经有一个html+css+js的静态网站 登录: php连接数据库,读取数据. <?php $username = root; $userpass = shao ...
- springboot oauth 鉴权之——password鉴权相当于jwt鉴权模式
近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验. 第一步:什么是 OAuth鉴权 OAuth2是工业标准的授权协议.OAuth2取代了在2006创建的原始OAuthTM协议所做的工作. ...