掌上游戏机开发指南GBA探索日记(9)(转)[@more@]  这一节我们讨论如何正常结束声音播放的问题。不要觉得这是个小问题,当初这个小问题难倒了我们所有研究GBA的爱好者。我总觉得这一点似乎是GBA设计上的缺陷,但是最后我们可以通过使用VBlank中断还解决这个问题。本篇结束的时候,我还会给出完整声音播放的代码。这样,你甚至不必了解声音播放的细节就可以实现声音的播放功能了。    由于声音播放使用的DMA不能根据WORD COUNT来控制传输的数据量,同时又不能在传输完毕的时候产生DMA中断,所以我们无法知道什么时候DMA把我们的音频数据传输完毕。这样,我们必须自己另外加一计时器,来计算什么时候声音播放结束。当然,你可以使用Timer来做,但是另外再设置个Timer似乎就麻烦了点,而且Timer的精度过高,也不好计算长时间的声音播放。依照官方开发包中的做法,我们就拿VBlank中断作为声音播放的计时器。    VBlank中断是在硬件扫描屏幕V方向扫描线的时候产生的硬件中断。它是严格的每秒59.78次(接近60次/s)    下面我们来看看这段修改后的播放声音的代码。需要注意拿他和前一节的播放代码来比较一下,看看他们之间有什么不同。    这个PlayDirectSoundA的播发函数多了一个参数u32 time.它就是用来控制声音结束的时间参数。它的单位是秒(对于一般的声音播放来说,秒单位应该是足够精确了)。    soundATime = time * 59.727;    这条代码是将实际播放时间的秒数转换成一共要产生VBlank的中断数。前面说过,我们将使用VBlank来判断我们的声音是否播放结束。而VBlank中断的频率是59.727Hz,也就是说一秒中要产生59.727次。比如说如果我们的这段声音要播放5秒钟,那么播放过程中一共要产生5*59.727次VBlank中断。这样,我们只要使用一个计数器,每次VBlank中断产生的时候计数器自加1,当它等于5*59.727的时候,那么声音也就应该结束了。    其它的代码就差不多和前一节的PlayDirectSoundA差不多了。    PlayDirectSoundA/    // time是播发时间,单位是秒数    void PlayDirectSoundA(u8 *sound, u16 sampleRate, u32 length,u32 time)    {    //Stop any previous sample    soundAPlaying = 0;    *(vu16 *)REG_TM0CNT_H = 0;    *(vu16 *)REG_TM0CNT_L = 0;    *(vu32 *)REG_DMA1SAD = 0;    *(vu16 *)REG_DMA1CNT_H = 0;    *(vu32 *)REG_DMA1DAD = 0;    //Output DirectSound A to right channel    *(vu16 *)REG_SOUNDCNT_H |= DSOUND_A_RIGHT_CHANNEL| DSOUND_A_TIMER_0 | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET | DSOUND_A_OUTPUT_FULL;    //Enable all sound    *(vu16 *)REG_SOUNDCNT_X |= SOUND_MASTER_ENABLE;    //DMA1 Source Addresss    *(vu32 *)REG_DMA1SAD = (u32)sound;    //Set sound A's current sound    soundA = sound;    //Set the length, looping, etc    soundALength = length;    // 讲time秒转换成V-Blank中断次数,V-Blank中断是59.727Hz    soundATime = time * 59.727;    soundACurrent = 0;    soundASampleRate = sampleRate;    //DMA1 Destination Address (REG_SGFIFOA)    *(vu32 *)REG_DMA1DAD = 0x40000A0;    //Write 32 bits into 0x040000A0 (REG_SGFIF0A) every VSync    *(vu32 *)REG_DMA1CNT = DMA_DEST_FIXED | DMA_REPEATE | DMA_32 | DMA_TIMEING_SYNC_TO_DISPLAY | DMA_ENABLE;    //Sample Rate    *(vu16 *)REG_TM0CNT_L = 65536 - (16777216/sampleRate);    //Enable the timer    *(vu16 *)REG_TM0CNT_H = TIMER_ENABLE | TIMER_IRQ;    //The sound is playing    soundAPlaying = 1;    }    在这里我们增加了一个函数UpdateDirectSoundA.它的作用是判断Direct Sound A是否播放完毕的函数.它的代码很简单.每调用它一次,当前计数器soundACurrent自加1,同时判断是否播放完毕.    /UpdateDirectSoundA    void UpdateDirectSoundA(void)    {    // if now is not playing sound A,return    if(!soundAPlaying)    return;    // Increase the Current timer    soundACurrent +=1;    // If sound A play time is up,close the sound A    if(soundACurrent >= soundATime)    CloseDirectSoundA();    }    需要注意的是,这个函数的调用必须是放在VBlank中断的响应函数里.比如像下面一样,把它的调用放在Interrupt中处理VBlank的部分里.这样我们才能保证它是每1/59.727秒被调用一次.    关于中断的部分,请看看前面的<>有关中断的部分.    void Interrupts(void)    {    u16 Int_Flag;    REG_IME = 0x00;      // Disable interrupts    Int_Flag = REG_IF;     // Read the interrupt flags    if((REG_IF & 1) == 1)    {    UpdateDirectSoundA();    }    REG_IF = Int_Flag;     // Write back the interrupt flags    REG_IME = 1;    // Re-Enable interrups    }    好了.这个如何控制声音播放结束的问题总算解决了.其实我们也可以使用Timer用同样的原理来控制声音播放的结束,不过至少我觉得Timer的中断产生频率太快,完全没有必要.下面我将把我播放声音的全部代码公布出来,你可以将它拷贝到libsound.c和libsound.h,然后就可以使用了.    随便在结束本节之前再说几句,我们关于GBA的基础部分也就结束.但是我们对于GBA开发的探索还没有结束.后面的GBA探索日记将介绍一些实际游戏开发过程中需要的技术,比如汉字显示,Tile模式下写点等问题.不过这些问题就和我们一直走的官方开发包没有关系(无论是日本人还是老美根本不会去考虑汉字显示的问题),但是这些技术在实际开发过程中是很有用的.特别是汉字显示和Tile下写点这两个问题,是很多朋友都在做的,现在应该说是比较成熟的,所以在后面的两篇日记里,我也将它们公布出来,希望对大家有所帮助.    //*************************************    //  文件名: libsound.h    //  GBA中Direct Sound处理函数或宏    //  tangl_99 创建于2003.2.7    //*************************************    #ifndef _SOUND_H    #define _SOUND_H    //Necessary Includes/    //Definitions/    #define BIT00 1    #define BIT01 2    #define BIT02 4    #define BIT03 8    #define BIT04 16    #define BIT05 32    #define BIT06 64    #define BIT07 128    #define BIT08 256    #define BIT09 512    #define BIT10 1024    #define BIT11 2048    #define BIT12 4096    #define BIT13 8192    #define BIT14 16384    #define BIT15 32768    #define TIMER_CASCADE  BIT02    #define TIMER_IRQ    BIT06    #define TIMER_ENABLE  BIT07    #define DMA_ENABLE               0x80000000    #define DMA_INTERUPT_ENABLE           0x40000000    #define DMA_TIMEING_IMMEDIATE          0x00000000    #define DMA_TIMEING_VBLANK           0x10000000    #define DMA_TIMEING_HBLANK           0x20000000    #define DMA_TIMEING_SYNC_TO_DISPLAY       0x30000000    #define DMA_16                 0x00000000    #define DMA_32                 0x04000000    #define DMA_REPEATE               0x02000000    #define DMA_SOURCE_INCREMENT          0x00000000    #define DMA_SOURCE_DECREMENT          0x00800000    #define DMA_SOURCE_FIXED            0x01000000    #define DMA_DEST_INCREMENT           0x00000000    #define DMA_DEST_DECREMENT           0x00200000    #define DMA_DEST_FIXED             0x00400000    #define DMA_DEST_RELOAD             0x00600000 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8225414/viewspace-951688/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8225414/viewspace-951688/

掌上游戏机开发指南GBA探索日记(9)(转)相关推荐

  1. 掌上游戏机开发指南——GBA程序开发入门

    1.GBA简介 Game Boy Advanced(GBA)是日本任天堂公司于2001年推出的一款32位掌上游戏机.它着重于游戏机的便携式,并且以2D游戏为主(3D游戏依然不错).GBA有十分高效硬件 ...

  2. 将前端技术栈移植到掌上游戏机

    https://juejin.im/post/5df89b96518825125b21d0f6 前端工程师,我们编写的代码只能活在浏览器.小程序或者 Node 进程里,这似乎已经成为了一种常识.但这就 ...

  3. 新的掌上游戏机,首款防作弊的开放式硬件设备以及更多游戏新闻

    您好,开放游戏迷! 在本周的版本中,我们将介绍GCW-ZERO手持式控制台,第一个防作弊的开放式硬件设备以及更多内容. 公开游戏摘要:2015年3月15日至21日 手持式控制台:GCW-ZERO 查看 ...

  4. 如果有一天,掌上游戏机的屏幕可以卷起来……

    随着智能手机以及手机游戏的发展,已经把当年像PSP.PSV这样火爆一时的掌上游戏机彻底钉在了历史的长河底下,现在还剩下的掌机就都是那种把当年的小霸王游戏或者仙剑1代这种像素游戏装进去的掌上红白机,怀旧 ...

  5. 【DIY】手把手教你爆改一台手机制作掌上游戏机

    开头声明: 此篇文章为本人原创,首发于酷安,转载请标明出处 这个游戏机的创意并非本人原创,创意来自B站UP主极客湾,在B站搜索"自制掌机"就可以看见相关视频视频转送门 这是一篇混合 ...

  6. GBA探索日记(-)

    GBA探索日记(-) mode0-2的BG与VRAM GBA的VRAM总共96KB,在mode3-5中,VRAM跟计算机的显示内存一样.屏幕上一个点对应一个显示内存地址. 可以看看下面两个函数,都是在 ...

  7. 1 分钟 Serverless 部署掌上游戏机,“一行命令”找回小时候的乐趣!

    简介:夏日大作战,体验极速部署的乐趣! 来源 | 阿里云开发者公众号 Serverless 以其快速交付.智能弹性.高可用性.低成本等核心价值成为云计算中一股新生力量,获得无数开发者的青睐. 为了让更 ...

  8. 任天堂3D掌上游戏机3DS正式发布

    本文转自掌上数码 http://www.pocketdigi.com/201006/201.html 在周二的E3视频游戏展上,任天堂推出了裸眼可玩3D游戏和看3D电影的3D掌上游戏机--3DS,有蓝 ...

  9. C#在Linux上的开发指南

    本人才疏学浅,在此记录自己用C#在Linux上开发的一点经验,写下这篇指南.(给想要在Linux上开发C#程序的朋友提供建议) 目前在Linux上跑的网站:http://douxiubar.com | ...

最新文章

  1. 要在某一房间中两台计算机之间实现网络通信,大学计算机计算思维导论期末考试综述.doc...
  2. 【性能优化实战】java嵌入式开发pos
  3. 018_switch语句
  4. 分布式、高并发、多线程,到底有什么区别?
  5. uva 10271——Chopsticks
  6. React Hooks的使用(三)——useRef、useImperativeHandle、useLayoutEffect解析、自定义Hook
  7. 树叶贴画机器人_洪山广场举办“落叶节”,树叶树枝拼贴出冬日风景
  8. MATLAB调用USB摄像头实现过程
  9. GOF之结构型模式Ⅱ(重点)
  10. 关于跨域问题的解决办法
  11. 静态方法获取spring的bean实例
  12. tesseract win 训练
  13. winpython anaconda_Windows:安装 Anaconda《 Python:基础 》
  14. kafka--Struct Streaming--kafka案例
  15. 京东app优惠券python抓取_备战双十一,scrapy框架爬取京东优惠券信息
  16. 自制中文编程语言一(语言设计一)
  17. 英文的pdf文件怎么翻译成中文
  18. android电视播放器字幕,android播放视频显示字幕
  19. 王者荣耀同一微信号多个服务器,王者荣耀微信怎么切换账号?打不上省排?那就换个荣耀战区好了...
  20. kali的vmtool工具安装

热门文章

  1. nvm管理node版本 node/npm不是内部或外部命令,也不是可运行的程序
  2. 程序员的叹息 (来自堕落兽人)
  3. python3 32位安装_【转载】python3安装scrapy之windows32位爬坑
  4. 8条战术教你正确分析游戏性能问题
  5. Git分布式版本控制和远程库创建运用、git常用指令【尚硅谷笔记】
  6. 2018天猫双11各类目品牌成交额top10排行榜
  7. 如何在手机TIM中使用QQ打卡
  8. jquery绑定点击事件形参_jquery click事件的可选参数data的作用
  9. BUG++:“expect ‘:‘ at 0, actual =“问题处理
  10. c语言抽签系统_C语言程序设计50例(经典收藏)