14413|17

603

帖子

1

TA的资源

纯净的硅(中级)

楼主
 

【试用心得】外传——《手把手教你移植InfoNES(到HANKER-LM4F232)》更新至20131017 [复制链接]

未完待续……更新至2013.10.17 - 20:50 温馨提示,本文中每个部分设计到的工程包括源文件,都可以在本文的最后发现下载链接哟! 应各路童鞋的围观,“写一个 《手把手教你移植XXX》神马的教程哎~” 实在太忙了,也没有什么好题材的移植,也就是这个InfoNES吧。因为我之前帖子里用的都是我原来学习NES时找到的源码,结构被我改了一通,支持的mapper也少,恰有童鞋提醒,研究InfoNES的信息也不少,我也就凑热闹来搞这个了。 有童鞋问了,神马是InfNES?这是一款NES游戏模拟器,也就是任天堂的红白机,80后的童年……InfoNES可以很容易地被移植到各个平台,可以说各大开发论坛上都可见它的身影。 说起移植,其实好的移植题材就是一个巴掌拍不响,既要有好的移植手法,同样的移植目标也就是源代码也本就有好的代码结构,具有良好的可移植性。否则源码不好,移植工作可能就变成了重构,任务量变大了不说,一点移植的快乐都没有了,而对源码不甚了解的童鞋,可能移植成功率也非常低了,可以说移植还不如重写。 这次选择的InfoNES就是一个良好的可移植性软件,它将与环境有关的内容都清出了软件内核,并且单独集合于一个InfoNES_System.h中,我们要做的就是实现这里提到的各种函数,再把InfoNES加入到我们的工程中一起联编。 要是像上面这样说的这样容易就好了,事实证明,道路阻且长。所以接下来我们尽量(在有关大道理上)说得细一点,以让更多不同水平段的童鞋在相关情节上多体会一些东西。如果你是有关技术的老鸟,那不好意思你可能什么都学不到了,更可能会发现本文的诸多错误,阅读本文只会让你更多地浪费生命,对此我十分抱歉。 好吧,节目开始。 第一部分是移植的前期工作 首先, 要准备好两个工程,一个是InfoNES的源工程(有码,本文的最后首先分享InfoNES的源码,在网上淘到的,里面还有win32工程和Linux工程,大家可以先编编看。),一个是我们自己的工程,其实移植初期,我们的工程越简单越好,目的就是为了让InfoNES适应我们的环境,这里我就借用青风侠赠送光盘中的《实验十五:液晶屏的显示》。事实上你会知道扯那么多没有用,在这次移植中我们只需要用到一些基本函数,尤其是液晶屏显示相关的内容,剩下的,我们从0开始:
  1. int main(void)
  2. {
  3. //初始化液晶屏幕;此处代码根据你的实际环境从开发板配套实例中复制
  4. while(1);
  5. }
复制代码
这样应该就足够了。 当然更多通常的东西我还没有指出,比如对于一些开发板,你需要首先关闭看门狗,初始化时钟控制,初始化相关端口,等等之类的,一般都可以在你的开发例程中找到。关于移植所需的最小环境,详情请查阅芯片手册和开发板的学习指南。实在不行可以找卖给你板子的那个人帮你配置一下(哎,店家,你打我干什么),但是这样实在不像我们作为一个开发者的良好选择。 其次, 很重要的,你应该确保前一步准备的东东都是好用的,谁都不希望移植一个软件,搞了一个月都不成功,最后发现是开发板的RAM有问题导致的。如何确认自己的开发板是好用的,没有那么复杂,可是也并不简单,我也没有什么好办法,童鞋们开新帖讨论吧,呵呵。 对于InfoNES是否好用,我已经试过了,可以用VC6.0打开其中的win32工程,编译运行,只可惜是日文版的。 最后, 作为承前启后的一件事,你要搞清楚接下来要做什么。别傻了,我们不可能知道之后每一个细节会怎样,所以这里的搞清楚也不是面面俱到,记得,不要总是急着一口气完成任务,之后我们的道路应该是一步一个脚印。 作为移植这一工作的基础,首先要把目标代码整合到我们的工程里。所以接下来我们就来做整合的工作。整合的工作,不必考虑更多的诸如编译之类的细节。 第二部分是将目标代码整合到我们的工程中,并完成之间的接口。 别担心,这一过程要完成的接口很简单:它提供的接口,我们就调用一下;它需要我们准备的接口,就写一个空函数。 首先, 把InfoNES的源码加入我们的工程。 InfoNES的核心代码很简单的,只有如图选中的这些文件(夹)是我们的工程中所需要的,但是我不建议你删除掉其他的内容。作为示例,我保留了win32的工程,以便我可以用VC对这些我改动的文件进行编译,以确定我们将来对代码进行的手术也都是可移植性强的。 工程中引入相关代码,其实只需要引入上面的cpp文件,只有4个。有童鞋会问,看到mapper文件夹中有大量的cpp文件,不必引入么?放心,InfoNES_Mapper.cpp文件已经Include了那些源文件,而且不存在路径问题,大胆地忽视它们吧! 相关头文件的路径应当正确设置。 其次, 实现InfoNES所需的函数。这些函数统统被定义在了InfoNES_System.h文件中。我们可以把它们复制出来,都扩展为空函数。为了整洁,我们单独创建一个c文件。
  1. /*-------------------------------------------------------------------*/
  2. /* InfoNES_system.c */
  3. /*-------------------------------------------------------------------*/
  4. #include "InfoNES.h"
  5. /*-------------------------------------------------------------------*/
  6. /* Palette data */
  7. /*-------------------------------------------------------------------*/
  8. WORD NesPalette[64]={
  9. 0
  10. };
  11. /*-------------------------------------------------------------------*/
  12. /* Function prototypes */
  13. /*-------------------------------------------------------------------*/
  14. /* Menu screen */
  15. int InfoNES_Menu()
  16. {
  17. return 0;
  18. }
  19. /* Read ROM image file */
  20. int InfoNES_ReadRom( const char *pszFileName )
  21. {
  22. return 0;
  23. }
  24. /* Release a memory for ROM */
  25. void InfoNES_ReleaseRom()
  26. {
  27. }
  28. /* Transfer the contents of work frame on the screen */
  29. void InfoNES_LoadFrame()
  30. {
  31. }
  32. /* Get a joypad state */
  33. void InfoNES_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem )
  34. {
  35. }
  36. /* memcpy */
  37. void *InfoNES_MemoryCopy( void *dest, const void *src, int count )
  38. {
  39. return NULL;
  40. }
  41. /* memset */
  42. void *InfoNES_MemorySet( void *dest, int c, int count )
  43. {
  44. return NULL;
  45. }
  46. /* Print debug message */
  47. void InfoNES_DebugPrint( char *pszMsg )
  48. {
  49. }
  50. /* Wait */
  51. void InfoNES_Wait()
  52. {
  53. }
  54. /* Sound Initialize */
  55. void InfoNES_SoundInit( void )
  56. {
  57. }
  58. /* Sound Open */
  59. int InfoNES_SoundOpen( int samples_per_sync, int sample_rate )
  60. {
  61. return 0;
  62. }
  63. /* Sound Close */
  64. void InfoNES_SoundClose( void )
  65. {
  66. }
  67. /* Sound Output 5 Waves - 2 Pulse, 1 Triangle, 1 Noise, 1 DPCM */
  68. void InfoNES_SoundOutput(int samples, BYTE *wave1, BYTE *wave2, BYTE *wave3, BYTE *wave4, BYTE *wave5)
  69. {
  70. }
  71. /* Print system message */
  72. void InfoNES_MessageBox( char *pszMsg, ... )
  73. {
  74. }
复制代码
最后, 我们需要调用InfoNES的一些函数。我从win32工程入手,发现启动InfoNES相关的一段代码:
  1. case IDC_BTN_OPEN:
  2. /*-------------------------------------------------------------------*/
  3. /* Open button */
  4. /*-------------------------------------------------------------------*/
  5. // Do nothing if emulation thread exists
  6. if (NULL != m_hThread)
  7. break;
  8. memset( &ofn, 0, sizeof ofn );
  9. szFileName[ 0 ] = '\0';
  10. ofn.lStructSize = sizeof ofn;
  11. ofn.hwndOwner = hWnd;
  12. ofn.hInstance = wc.hInstance;
  13. ofn.lpstrFilter = NULL;
  14. ofn.lpstrCustomFilter = NULL;
  15. ofn.nMaxCustFilter = 0;
  16. ofn.nFilterIndex = 0;
  17. ofn.lpstrFile = szFileName;
  18. ofn.nMaxFile = sizeof szFileName;
  19. ofn.lpstrFileTitle = NULL;
  20. ofn.nMaxFileTitle = 0;
  21. ofn.lpstrInitialDir = NULL;
  22. ofn.lpstrTitle = NULL;
  23. ofn.Flags = 0;
  24. ofn.nFileOffset;
  25. ofn.nFileExtension = 0;
  26. ofn.lpstrDefExt = NULL;
  27. ofn.lCustData = 0;
  28. ofn.lpfnHook = NULL;
  29. ofn.lpTemplateName = NULL;
  30. if ( GetOpenFileName( &ofn ) )
  31. {
  32. // Load cassette
  33. if ( InfoNES_Load( szFileName ) == 0 )
  34. {
  35. // Set a ROM image name
  36. strcpy( szRomName, szFileName );
  37. // Load SRAM
  38. LoadSRAM();
  39. // Create Emulation Thread
  40. m_hThread=CreateThread((LPSECURITY_ATTRIBUTES)NULL, (DWORD)0,
  41. (LPTHREAD_START_ROUTINE)InfoNES_Main, (LPVOID)NULL, (DWORD)0, &m_ThreadID);
  42. }
  43. }
  44. break;
复制代码
细节都不需要太关注啦,整体的内容大概是弹出打开文件的对话框,然后选择某个文件,再把文件名传递给InfoNES_Load,当它返回0就表示成功,这样就打开一个线程来执行InfoNES_Main。作为一个模拟器,它一旦跑起来就不需要我们控制了(事实可能不是这样,呵呵),所以到这为止就能和模拟器成功对接了。于是我们也在main函数中调用这两个函数。
  1. #include "InfoNES.h"
  2. int main(void)
  3. {
  4. if(InfoNES_Load(NULL) == 0)
  5. {
  6. InfoNES_Main();
  7. }
  8. while(1);
  9. }
复制代码
太棒了,我的工程里有InfoNES模拟器了! 太简单了,这就是移植啊。 点编译……我Sh~it!!!!!!!! ============================以下,2013.10.17续============================================ 第三部分是让工程编译成功 首先我重新整理的工程结构,使得Keil工程也和Win32工程一样并列在那里。 开始编译了,从我的开发经验上说,为了避免不必要的麻烦,即使是warning,也应当看一看要不要修改。所以我们来检查一下都有哪些东西要改的。 各位童鞋编译的结果也不各不相同,暂时以我的为主,依照我的顺序进行修改吧: 1 ..\InfoNES.h(285): warning: #1295-D: Deprecated declaration InfoNES_Init - give arg types 这种问题主要是在我们的编译环境里,即使是没有参数,也最好是指定为(void),所以在InfoNES.h(285行)做修改: 由
  1. /* Initialize InfoNES */

    void InfoNES_Init();

复制代码
改为
  1. /* Initialize InfoNES */

    void InfoNES_Init(void);

复制代码
同样的过程,对其他相同的warning进行处理。 2 ..\InfoNES.cpp(634): warning: #175-D: subscript out of range 这里是说对数组的访问,貌似越界了,这种事可是我们程序开发的大忌,必须改。 在相应位置找到代码
  1. APU_Reg[ 0x4015 ] |= 0x40;
复制代码
注意到这是模拟操作APU的寄存器,是处理声音的。这样吧,本篇还是基于HANKER-LM4F232的,暂时没有处理声音的能力,那么和我一起,把所有的APU相关的代码都停用了吧。 停用代码,我建议使用编译预开关,不是#if 0,而是这样: 在infones_types.h中定义一处:
  1. /*-------------------------------------------------------------------*/
  2. /* Config */
  3. /*-------------------------------------------------------------------*/
  4. #define APU_NONE
复制代码
之后要处理好多地方了:根据组个修改变更,行号也会有所变化,如果你是根据我的说明做的,请严格按照顺序,否则请自行搜索相关代码。我会附带上变更后的前后两行代码,以做定位参考。 详细请参考13楼的内容。 停用了APU的代码,接下来处理其他的数组访问越界:我大概看了下,基本都是正经的访问越界了。在不知道具体含义的情况下,我们可以选择扩大定义时的大小。 详细请参考14楼的内容。 3 ..\K6502_rw.h(121): warning: #111-D: statement is unreachable 这处错误,观察一下,好像是编码习惯不好,不过效率会提高一点,暂时可以忽略不改。 经过再次编译确认,就剩下Link错误了。 4 .\output\InfoNES.axf: Error: L6218E: Undefined symbol InfoNES_Load (referred from main.o). 这种错误很可恶。 读一读错误的信息,它说我没有定义InfoNES_Load的实体,可是我明明能够找到这个函数的实现啊……为什么链结不到呢?经过检查工程,可以看到,这个实体实际上定义在cpp文件中,而调用它的main函数我却定义在c文件中,这时候就涉及到一个知识点:C和C++混合编程。详细信息请各位自行搜索相关内容。 说说处理方案,经过仔细检查,InfoNES的源码均是由纯C语言编写的,所以嘛……哎,可不是把cpp都改成c哟!否则其他的工程就都彪了!处理方案是在所有InfoNES的源码中头尾加上extern "C" {......}。详细参考文末的附件吧。 再编译,就不会出现头疼的L6218E了。 但是出现了更加让人抓狂的Link错误: .\output\InfoNES.axf: Error: L6406E: No space in execution regions with .ANY selector matching infones_mapper.o(.bss). .\output\InfoNES.axf: Error: L6406E: No space in execution regions with .ANY selector matching infones.o(.bss). .\output\InfoNES.axf: Error: L6407E: Sections of aggregate size 0x9535c bytes could not fit into .ANY selector(s). 我无法解释,但是我知道这两个错误意味着RAM不够了!(呵呵,详情请具体学习关于分散加载中的各种概念,例如这里就出现了.ANY,.bss,这些都是神马?欢迎大家继续深入学习。) 修改方案: 1.打开工程选项对话框,参见下图的标签页,IRAM1就是片上RAM,请调整它的大小,例如我在它后面加了两个0成为0x800000,记得点[OK] 2.还是工程选项对话框,如下图的标签页里,如果发现ScatterFile一项里有内容,那么就点击其后的[Edit...],之后关闭工程选项,在代码编辑区可以发现这个文件已经被打开,找到如“RW_IRAM 0x20000000 0x0008000”一行,修改后面的大小,和修改方案1中的思路一样,它就表示RAM的大小。记得保存。 再编译一次吧…… linking... Program Size: Code=150964 RO-data=32 RW-data=2360 ZI-data=614976 ".\output\InfoNES.axf" - 0 Error(s), 4 Warning(s). 大功告成,我们成功把InfoNES编译在我们的工程里啦!喜大普奔的好消息 什么嘛,这样根本就没法运行啊! 哦,累了,休息,休息一会儿…… 小结:移植中不免要修改源码,修改之前千万要尽量搞清楚源码的含义,修改操作也应该是可移植性强的。如果修改破坏了移植性,就会给将来的移植带来麻烦。 第一部分资源: InfoNES源码包 InfoNES097JRC1_SDL.7z (110 KB, 下载次数: 333) 第二部分资源 : 我们的InfoNES工程 Prj20131014.rar (256.77 KB, 下载次数: 212) 第三部分 编译成功的工程 prj20131017.7z (116.67 KB, 下载次数: 252) [ 本帖最后由 sjtitr 于 2013-10-17 21:35 编辑 ]

最新回复

666   详情 回复 发表于 2024-8-23 11:09

点评

请问楼主,能往STM32上移植不  详情 回复 发表于 2013-10-15 09:21
不错,顶.  详情 回复 发表于 2013-10-14 12:26
 
点赞(1) 关注(3)

回复
举报

5015

帖子

13

TA的资源

裸片初长成(初级)

沙发
 
帮顶
 
个人签名《MCU工程师炼成记》作者之一
 

回复

1803

帖子

0

TA的资源

五彩晶圆(高级)

板凳
 

回复 楼主sjtitr 的帖子

不错,顶.
 
 
 

回复

1万

帖子

16

TA的资源

版主

4
 

InfoNES 是什么东东????

 
个人签名http://shop34182318.taobao.com/
https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
 
 

回复

437

帖子

0

TA的资源

五彩晶圆(初级)

5
 
目测要过W  :carnation:

点评

是说工资么…:titter:  详情 回复 发表于 2013-10-15 10:18
 
个人签名
 
 

回复

373

帖子

0

TA的资源

纯净的硅(中级)

6
 

回复 楼主sjtitr 的帖子

请问楼主,能往STM32上移植不

点评

没问题,到目前为止还没有特别需要特定板子的内容。内存的话,我的板子是32K,ROM256K吧,我希望你的不要再小了,不然后面会很麻烦:)  详情 回复 发表于 2013-10-15 09:37
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

7
 

回复 6楼wudayongnb 的帖子

没问题,到目前为止还没有特别需要特定板子的内容。内存的话,我的板子是32K,ROM256K吧,我希望你的不要再小了,不然后面会很麻烦

点评

OK,我的是RAM64K,flash 512k,楼主赶快更新啊,话说楼主更新的话还是在这个帖子上吗?  详情 回复 发表于 2013-10-15 15:54
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

8
 

回复 5楼juring 的帖子

是说工资么…
 
 
 

回复

373

帖子

0

TA的资源

纯净的硅(中级)

9
 

回复 7楼sjtitr 的帖子

OK,我的是RAM64K,flash 512k,楼主赶快更新啊,话说楼主更新的话还是在这个帖子上吗?
 
 
 

回复

373

帖子

0

TA的资源

纯净的硅(中级)

10
 
我用VS2008编译其中的win32工程,出现
fatal error C1083: 无法打开包括文件:“dsound.h”: No such file or directory,请问楼主该怎么解决

点评

我计划都更新在这。最近感冒了,得休息休息。你问的头文件应该是win库函数头,我没有研究,网上有许多信息。我用vs2012直接编过了  详情 回复 发表于 2013-10-15 19:13
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

11
 

回复 10楼wudayongnb 的帖子

我计划都更新在这。最近感冒了,得休息休息。你问的头文件应该是win库函数头,我没有研究,网上有许多信息。我用vs2012直接编过了
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

12
 

aaaa

wa o
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

13
 

回复 楼主sjtitr 的帖子

K6502_rw.h:
131-144
  1.       if ( wAddr == 0x4015 )
  2.       {
  3. #ifndef APU_NONE
  4.         // APU control
  5.         byRet = APU_Reg[ 0x4015 ];
  6.         if ( ApuC1Atl > 0 ) byRet |= (1<<0);
  7.         if ( ApuC2Atl > 0 ) byRet |= (1<<1);
  8.         if (  !ApuC3Holdnote ) {
  9.           if ( ApuC3Atl > 0 ) byRet |= (1<<2);
  10.         } else {
  11.           if ( ApuC3Llc > 0 ) byRet |= (1<<2);
  12.         }
  13.         if ( ApuC4Atl > 0 ) byRet |= (1<<3);

  14.         // FrameIRQ
  15.         APU_Reg[ 0x4015 ] &= ~0x40;
  16. #else
  17.                 byRet = 0;
  18. #endif /* APU_NONE */
  19.         return byRet;
复制代码


387-389
  1.         case 0x13:
  2. #ifndef APU_NONE
  3.           // Call Function corresponding to Sound Registers
  4.           if ( !APU_Mute )
  5.             pAPUSoundRegs[ wAddr & 0x1f ]( wAddr, byData );
  6. #endif /* APU_NONE */
  7.           break;
复制代码


425
  1.         case 0x15:  /* 0x4015 */
  2. #ifndef APU_NONE
  3.           InfoNES_pAPUWriteControl( wAddr, byData );
  4. #endif /* APU_NONE */
  5. #if 0
  6.           /* Unknown */
  7.           if ( byData & 0x10 )
复制代码


438-441
  1.         case 0x16:  /* 0x4016 */
  2. #ifndef APU_NONE
  3.                   // For VS-Unisystem
  4.                   MapperApu( wAddr, byData );
  5.           // Reset joypad
  6.           if ( !( APU_Reg[ 0x16 ] & 1 ) && ( byData & 1 ) )
  7. #else
  8.           // Reset joypad
  9.           if ( byData & 1 )
  10. #endif /* APU_NONE */
  11.           {
  12.             PAD1_Bit = 0;
复制代码


467-468
  1.       if ( wAddr <= 0x4017 )
  2.       {
  3. #ifndef APU_NONE
  4.         /* Write to APU Register */
  5.         APU_Reg[ wAddr & 0x1f ] = byData;
  6. #endif /* APU_NONE */
  7.       }
  8.       else
复制代码


InfoNES_pAPU.h:
11
  1. #define InfoNES_PAPU_H_INCLUDED

  2. #include "InfoNES_Types.h"
  3. #ifndef APU_NONE

  4. /*-------------------------------------------------------------------*/
  5. /*  Macros                                                           */
  6. /*-------------------------------------------------------------------*/
复制代码


198
  1. extern BYTE  ApuC4Atl;
  2. #endif /* APU_NONE */
  3. #endif /* InfoNES_PAPU_H_INCLUDED */

  4. /*
复制代码


InfoNES_pAPU.cpp:
17
  1. #include "InfoNES_pAPU.h"

  2. #ifndef APU_NONE

  3. /*-------------------------------------------------------------------*/
  4. /*   APU Event resources                                             */
  5. /*-------------------------------------------------------------------*/
复制代码


1068
  1.   InfoNES_SoundClose();
  2. }

  3. #endif /* APU_NONE */

  4. /*
  5. * End of InfoNES_pAPU.cpp
  6. */
复制代码


InfoNES.h
211
  1. /*-------------------------------------------------------------------*/
  2. /*  APU and Pad resources                                            */
  3. /*-------------------------------------------------------------------*/

  4. #ifndef APU_NONE
  5. extern BYTE APU_Reg[];
  6. extern int APU_Mute;
  7. #endif /* APU_NONE */

  8. extern DWORD PAD1_Latch;
复制代码


InfoNES.cpp
189-193
  1. /*-------------------------------------------------------------------*/
  2. /*  APU and Pad resources                                            */
  3. /*-------------------------------------------------------------------*/

  4. #ifndef APU_NONE
  5. /* APU Register */
  6. BYTE APU_Reg[ 0x18 ];

  7. /* APU Mute ( 0:OFF, 1:ON ) */
  8. int APU_Mute = 0;
  9. #endif /* APU_NONE */

  10. /* Pad data */
  11. DWORD PAD1_Latch;
复制代码


296-297
  1. */
  2. #ifndef APU_NONE
  3.   // Finalize pAPU
  4.   InfoNES_pAPUDone();
  5. #endif /* APU_NONE */
复制代码


410
  1.   InfoNES_MemorySet( PalTable, 0, sizeof PalTable );

  2. #ifndef APU_NONE
  3.   // Reset APU register
  4.   InfoNES_MemorySet( APU_Reg, 0, sizeof APU_Reg );
  5. #endif /* APU_NONE */

  6.   // Reset joypad
  7.   PAD1_Latch = PAD2_Latch = PAD_System = 0;
复制代码


425-429
  1.   InfoNES_SetupPPU();

  2. #ifndef APU_NONE
  3.   /*-------------------------------------------------------------------*/
  4.   /*  Initialize pAPU                                                  */
  5.   /*-------------------------------------------------------------------*/

  6.   InfoNES_pAPUInit();
  7. #endif /* APU_NONE */

  8.   /*-------------------------------------------------------------------*/
  9.   /*  Initialize Mapper                                                */
  10.   /*-------------------------------------------------------------------*/
复制代码


642
  1.     if ( FrameStep > STEP_PER_FRAME && FrameIRQ_Enable )
  2.     {
  3.       FrameStep %= STEP_PER_FRAME;
  4.       IRQ_REQ;
  5. #ifndef APU_NONE
  6.       APU_Reg[ 0x4015 ] |= 0x40;
  7. #endif /* APU_NONE */
  8.     }
复制代码


741-742
  1. #ifndef APU_NONE
  2.       // pAPU Sound function in V-Sync
  3.       if ( !APU_Mute )
  4.         InfoNES_pAPUVsync();
  5. #endif /* APU_NONE */

  6.       // A mapper function in V-Sync
复制代码

[ 本帖最后由 sjtitr 于 2013-10-17 08:45 编辑 ]
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

14
 
InfoNES_Mapper_019.cpp
8
  1. BYTE  Map19_Regs[ 2 ];
复制代码
改为
  1. BYTE  Map19_Regs[ 3 ];
复制代码
InfoNES_Mapper_045.cpp
9
  1. DWORD Map45_C[4],Map45_Chr0, Map45_Chr1,Map45_Chr2, Map45_Chr3;
复制代码
改为
  1. DWORD Map45_C[8],Map45_Chr0, Map45_Chr1,Map45_Chr2, Map45_Chr3;
复制代码
 
 
 

回复

474

帖子

2

TA的资源

纯净的硅(初级)

15
 
火钳刘明~
 
 
 

回复

240

帖子

4

TA的资源

一粒金砂(中级)

16
 
本帖最后由 abszy 于 2014-9-3 16:20 编辑

很详细的讲解  这么好的帖子  mark
就是不知道 在分散加载处为什么直接在on-chip size的8000直接加两个0就行了,加3个不行吗
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

17
 
感谢大佬的无私奉献
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

18
 

666

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表