burn 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. data/LICENSE +621 -0
  2. data/README.md +467 -0
  3. data/Rakefile +1 -0
  4. data/bin/burn +14 -0
  5. data/lib/burn/builder.rb +65 -0
  6. data/lib/burn/cli.rb +187 -0
  7. data/lib/burn/debug.rb +25 -0
  8. data/lib/burn/dsl/channel_stream.rb +105 -0
  9. data/lib/burn/dsl/declare.rb +42 -0
  10. data/lib/burn/dsl/dsl_base.rb +31 -0
  11. data/lib/burn/dsl/music.rb +36 -0
  12. data/lib/burn/dsl/note.rb +125 -0
  13. data/lib/burn/dsl/scene.rb +278 -0
  14. data/lib/burn/dsl/sound.rb +30 -0
  15. data/lib/burn/dsl/sound_effect.rb +91 -0
  16. data/lib/burn/dsl.rb +8 -0
  17. data/lib/burn/generator/assembly_music.rb +47 -0
  18. data/lib/burn/generator/assembly_sound_effect.rb +33 -0
  19. data/lib/burn/generator/c_source.rb +54 -0
  20. data/lib/burn/generator/template/mus_template.s +49 -0
  21. data/lib/burn/generator/template/template.c +88 -0
  22. data/lib/burn/generator.rb +3 -0
  23. data/lib/burn/tools/mac/cc65/asminc/_file.inc +27 -0
  24. data/lib/burn/tools/mac/cc65/asminc/_heap.inc +35 -0
  25. data/lib/burn/tools/mac/cc65/asminc/apple2.inc +64 -0
  26. data/lib/burn/tools/mac/cc65/asminc/atari.inc +1175 -0
  27. data/lib/burn/tools/mac/cc65/asminc/atari.mac +59 -0
  28. data/lib/burn/tools/mac/cc65/asminc/atmos.inc +110 -0
  29. data/lib/burn/tools/mac/cc65/asminc/c128.inc +214 -0
  30. data/lib/burn/tools/mac/cc65/asminc/c16.inc +9 -0
  31. data/lib/burn/tools/mac/cc65/asminc/c64.inc +212 -0
  32. data/lib/burn/tools/mac/cc65/asminc/cbm.mac +50 -0
  33. data/lib/burn/tools/mac/cc65/asminc/cbm510.inc +182 -0
  34. data/lib/burn/tools/mac/cc65/asminc/cbm610.inc +110 -0
  35. data/lib/burn/tools/mac/cc65/asminc/cbm_filetype.inc +34 -0
  36. data/lib/burn/tools/mac/cc65/asminc/cpu.mac +24 -0
  37. data/lib/burn/tools/mac/cc65/asminc/ctype.inc +29 -0
  38. data/lib/burn/tools/mac/cc65/asminc/em-error.inc +49 -0
  39. data/lib/burn/tools/mac/cc65/asminc/em-kernel.inc +106 -0
  40. data/lib/burn/tools/mac/cc65/asminc/errno.inc +36 -0
  41. data/lib/burn/tools/mac/cc65/asminc/fcntl.inc +21 -0
  42. data/lib/burn/tools/mac/cc65/asminc/generic.mac +55 -0
  43. data/lib/burn/tools/mac/cc65/asminc/get_tv.inc +22 -0
  44. data/lib/burn/tools/mac/cc65/asminc/joy-error.inc +44 -0
  45. data/lib/burn/tools/mac/cc65/asminc/joy-kernel.inc +85 -0
  46. data/lib/burn/tools/mac/cc65/asminc/longbranch.mac +88 -0
  47. data/lib/burn/tools/mac/cc65/asminc/lynx.inc +279 -0
  48. data/lib/burn/tools/mac/cc65/asminc/modload.inc +78 -0
  49. data/lib/burn/tools/mac/cc65/asminc/mouse-kernel.inc +180 -0
  50. data/lib/burn/tools/mac/cc65/asminc/nes.inc +93 -0
  51. data/lib/burn/tools/mac/cc65/asminc/o65.inc +150 -0
  52. data/lib/burn/tools/mac/cc65/asminc/opcodes.inc +509 -0
  53. data/lib/burn/tools/mac/cc65/asminc/pet.inc +54 -0
  54. data/lib/burn/tools/mac/cc65/asminc/plus4.inc +86 -0
  55. data/lib/burn/tools/mac/cc65/asminc/ser-error.inc +54 -0
  56. data/lib/burn/tools/mac/cc65/asminc/ser-kernel.inc +162 -0
  57. data/lib/burn/tools/mac/cc65/asminc/signal.inc +57 -0
  58. data/lib/burn/tools/mac/cc65/asminc/smc.inc +245 -0
  59. data/lib/burn/tools/mac/cc65/asminc/stdio.inc +70 -0
  60. data/lib/burn/tools/mac/cc65/asminc/supervision.inc +76 -0
  61. data/lib/burn/tools/mac/cc65/asminc/tgi-error.inc +52 -0
  62. data/lib/burn/tools/mac/cc65/asminc/tgi-kernel.inc +234 -0
  63. data/lib/burn/tools/mac/cc65/asminc/tgi-vectorfont.inc +70 -0
  64. data/lib/burn/tools/mac/cc65/asminc/time.inc +59 -0
  65. data/lib/burn/tools/mac/cc65/asminc/utsname.inc +46 -0
  66. data/lib/burn/tools/mac/cc65/asminc/vic20.inc +75 -0
  67. data/lib/burn/tools/mac/cc65/asminc/zeropage.inc +26 -0
  68. data/lib/burn/tools/mac/cc65/bin/ca65 +0 -0
  69. data/lib/burn/tools/mac/cc65/bin/cc65 +0 -0
  70. data/lib/burn/tools/mac/cc65/bin/ld65 +0 -0
  71. data/lib/burn/tools/other/cc65/asminc/_file.inc +27 -0
  72. data/lib/burn/tools/other/cc65/asminc/_heap.inc +35 -0
  73. data/lib/burn/tools/other/cc65/asminc/apple2.inc +64 -0
  74. data/lib/burn/tools/other/cc65/asminc/atari.inc +1175 -0
  75. data/lib/burn/tools/other/cc65/asminc/atari.mac +59 -0
  76. data/lib/burn/tools/other/cc65/asminc/atmos.inc +110 -0
  77. data/lib/burn/tools/other/cc65/asminc/c128.inc +214 -0
  78. data/lib/burn/tools/other/cc65/asminc/c16.inc +9 -0
  79. data/lib/burn/tools/other/cc65/asminc/c64.inc +212 -0
  80. data/lib/burn/tools/other/cc65/asminc/cbm.mac +50 -0
  81. data/lib/burn/tools/other/cc65/asminc/cbm510.inc +182 -0
  82. data/lib/burn/tools/other/cc65/asminc/cbm610.inc +110 -0
  83. data/lib/burn/tools/other/cc65/asminc/cbm_filetype.inc +34 -0
  84. data/lib/burn/tools/other/cc65/asminc/cpu.mac +24 -0
  85. data/lib/burn/tools/other/cc65/asminc/ctype.inc +29 -0
  86. data/lib/burn/tools/other/cc65/asminc/em-error.inc +49 -0
  87. data/lib/burn/tools/other/cc65/asminc/em-kernel.inc +106 -0
  88. data/lib/burn/tools/other/cc65/asminc/errno.inc +36 -0
  89. data/lib/burn/tools/other/cc65/asminc/fcntl.inc +21 -0
  90. data/lib/burn/tools/other/cc65/asminc/generic.mac +55 -0
  91. data/lib/burn/tools/other/cc65/asminc/get_tv.inc +22 -0
  92. data/lib/burn/tools/other/cc65/asminc/joy-error.inc +44 -0
  93. data/lib/burn/tools/other/cc65/asminc/joy-kernel.inc +85 -0
  94. data/lib/burn/tools/other/cc65/asminc/longbranch.mac +88 -0
  95. data/lib/burn/tools/other/cc65/asminc/lynx.inc +279 -0
  96. data/lib/burn/tools/other/cc65/asminc/modload.inc +78 -0
  97. data/lib/burn/tools/other/cc65/asminc/mouse-kernel.inc +180 -0
  98. data/lib/burn/tools/other/cc65/asminc/nes.inc +93 -0
  99. data/lib/burn/tools/other/cc65/asminc/o65.inc +150 -0
  100. data/lib/burn/tools/other/cc65/asminc/opcodes.inc +509 -0
  101. data/lib/burn/tools/other/cc65/asminc/pet.inc +54 -0
  102. data/lib/burn/tools/other/cc65/asminc/plus4.inc +86 -0
  103. data/lib/burn/tools/other/cc65/asminc/ser-error.inc +54 -0
  104. data/lib/burn/tools/other/cc65/asminc/ser-kernel.inc +162 -0
  105. data/lib/burn/tools/other/cc65/asminc/signal.inc +57 -0
  106. data/lib/burn/tools/other/cc65/asminc/smc.inc +245 -0
  107. data/lib/burn/tools/other/cc65/asminc/stdio.inc +70 -0
  108. data/lib/burn/tools/other/cc65/asminc/supervision.inc +76 -0
  109. data/lib/burn/tools/other/cc65/asminc/tgi-error.inc +52 -0
  110. data/lib/burn/tools/other/cc65/asminc/tgi-kernel.inc +234 -0
  111. data/lib/burn/tools/other/cc65/asminc/tgi-vectorfont.inc +70 -0
  112. data/lib/burn/tools/other/cc65/asminc/time.inc +59 -0
  113. data/lib/burn/tools/other/cc65/asminc/utsname.inc +46 -0
  114. data/lib/burn/tools/other/cc65/asminc/vic20.inc +75 -0
  115. data/lib/burn/tools/other/cc65/asminc/zeropage.inc +26 -0
  116. data/lib/burn/tools/other/cc65/bin/ca65 +0 -0
  117. data/lib/burn/tools/other/cc65/bin/cc65 +0 -0
  118. data/lib/burn/tools/other/cc65/bin/ld65 +0 -0
  119. data/lib/burn/tools/win/cc65/asminc/_file.inc +27 -0
  120. data/lib/burn/tools/win/cc65/asminc/_heap.inc +35 -0
  121. data/lib/burn/tools/win/cc65/asminc/apple2.inc +64 -0
  122. data/lib/burn/tools/win/cc65/asminc/atari.inc +1101 -0
  123. data/lib/burn/tools/win/cc65/asminc/atmos.inc +31 -0
  124. data/lib/burn/tools/win/cc65/asminc/c128.inc +213 -0
  125. data/lib/burn/tools/win/cc65/asminc/c16.inc +9 -0
  126. data/lib/burn/tools/win/cc65/asminc/c64.inc +212 -0
  127. data/lib/burn/tools/win/cc65/asminc/cbm510.inc +182 -0
  128. data/lib/burn/tools/win/cc65/asminc/cbm610.inc +110 -0
  129. data/lib/burn/tools/win/cc65/asminc/ctype.inc +29 -0
  130. data/lib/burn/tools/win/cc65/asminc/em-error.inc +44 -0
  131. data/lib/burn/tools/win/cc65/asminc/em-kernel.inc +100 -0
  132. data/lib/burn/tools/win/cc65/asminc/errno.inc +36 -0
  133. data/lib/burn/tools/win/cc65/asminc/fcntl.inc +21 -0
  134. data/lib/burn/tools/win/cc65/asminc/get_tv.inc +22 -0
  135. data/lib/burn/tools/win/cc65/asminc/joy-error.inc +44 -0
  136. data/lib/burn/tools/win/cc65/asminc/joy-kernel.inc +85 -0
  137. data/lib/burn/tools/win/cc65/asminc/lynx.inc +273 -0
  138. data/lib/burn/tools/win/cc65/asminc/modload.inc +78 -0
  139. data/lib/burn/tools/win/cc65/asminc/mouse-kernel.inc +179 -0
  140. data/lib/burn/tools/win/cc65/asminc/nes.inc +93 -0
  141. data/lib/burn/tools/win/cc65/asminc/o65.inc +135 -0
  142. data/lib/burn/tools/win/cc65/asminc/pet.inc +45 -0
  143. data/lib/burn/tools/win/cc65/asminc/plus4.inc +87 -0
  144. data/lib/burn/tools/win/cc65/asminc/rs232.inc +19 -0
  145. data/lib/burn/tools/win/cc65/asminc/ser-error.inc +50 -0
  146. data/lib/burn/tools/win/cc65/asminc/ser-kernel.inc +161 -0
  147. data/lib/burn/tools/win/cc65/asminc/signal.inc +57 -0
  148. data/lib/burn/tools/win/cc65/asminc/stdio.inc +70 -0
  149. data/lib/burn/tools/win/cc65/asminc/supervision.inc +76 -0
  150. data/lib/burn/tools/win/cc65/asminc/tgi-error.inc +48 -0
  151. data/lib/burn/tools/win/cc65/asminc/tgi-kernel.inc +183 -0
  152. data/lib/burn/tools/win/cc65/asminc/tgi-mode.inc +48 -0
  153. data/lib/burn/tools/win/cc65/asminc/time.inc +59 -0
  154. data/lib/burn/tools/win/cc65/asminc/utsname.inc +46 -0
  155. data/lib/burn/tools/win/cc65/asminc/vic20.inc +77 -0
  156. data/lib/burn/tools/win/cc65/asminc/zeropage.inc +22 -0
  157. data/lib/burn/tools/win/cc65/bin/ca65.exe +0 -0
  158. data/lib/burn/tools/win/cc65/bin/cc65.exe +0 -0
  159. data/lib/burn/tools/win/cc65/bin/ld65.exe +0 -0
  160. data/lib/burn/util/os.rb +38 -0
  161. data/lib/burn/util/patternizer.rb +62 -0
  162. data/lib/burn/util/pxes.rb +180 -0
  163. data/lib/burn/util/server.rb +21 -0
  164. data/lib/burn/util.rb +4 -0
  165. data/lib/burn/version.rb +3 -0
  166. data/lib/burn/workspace_default/asset/crt0.s +260 -0
  167. data/lib/burn/workspace_default/asset/famitone.s +1031 -0
  168. data/lib/burn/workspace_default/asset/mus_instruments.s +50 -0
  169. data/lib/burn/workspace_default/asset/music.s +3 -0
  170. data/lib/burn/workspace_default/asset/nes.cfg +83 -0
  171. data/lib/burn/workspace_default/asset/neslib.h +213 -0
  172. data/lib/burn/workspace_default/asset/neslib.s +923 -0
  173. data/lib/burn/workspace_default/asset/runtime.lib +0 -0
  174. data/lib/burn/workspace_default/asset/sounds.s +143 -0
  175. data/lib/burn/workspace_default/asset/test.h +22 -0
  176. data/lib/burn/workspace_default/asset/tileset.chr +0 -0
  177. data/lib/burn/workspace_default/release/js/emulator.html +42 -0
  178. data/lib/burn/workspace_default/release/js/js/dynamicaudio-89ba58da476270a9b630.min.js +1 -0
  179. data/lib/burn/workspace_default/release/js/js/jquery-1.4.2.min.js +154 -0
  180. data/lib/burn/workspace_default/release/js/js/jsnes-4e7a7260aa.js +7149 -0
  181. data/lib/burn/workspace_default/release/js/swf/dynamicaudio.swf +0 -0
  182. data/lib/burn/workspace_default/scripts/compile.bat +30 -0
  183. data/lib/burn/workspace_default/scripts/compile.sh +30 -0
  184. data/lib/burn.rb +11 -0
  185. data/test/helper.rb +8 -0
  186. data/test/runner.rb +2 -0
  187. data/test/test_burn.rb +14 -0
  188. data/test/test_dsl.rb +22 -0
  189. data/test/test_pxes.rb +48 -0
  190. metadata +270 -0
@@ -0,0 +1,1031 @@
1
+ ;FamiTone audio library v1.24
2
+ ;by Shiru (shiru@mail.ru) 06'11
3
+ ;The name is suggested by Memblers from NesDev
4
+ ;Feel free to do anything you want with this code, consider it Public Domain
5
+
6
+
7
+
8
+
9
+ ;aliases for APU registers
10
+
11
+ APU_PL1_VOL = $4000
12
+ APU_PL1_SWEEP = $4001
13
+ APU_PL1_LO = $4002
14
+ APU_PL1_HI = $4003
15
+ APU_PL2_VOL = $4004
16
+ APU_PL2_SWEEP = $4005
17
+ APU_PL2_LO = $4006
18
+ APU_PL2_HI = $4007
19
+ APU_TRI_LINEAR = $4008
20
+ APU_TRI_LO = $400a
21
+ APU_TRI_HI = $400b
22
+ APU_NOISE_VOL = $400c
23
+ APU_NOISE_LO = $400e
24
+ APU_NOISE_HI = $400f
25
+ APU_DMC_FREQ = $4010
26
+ APU_DMC_RAW = $4011
27
+ APU_DMC_START = $4012
28
+ APU_DMC_LEN = $4013
29
+ APU_SND_CHN = $4015
30
+
31
+ ;all the FamiTone variables take 112+15*FT_SFX_STREAMS bytes in a RAM page
32
+
33
+ FT_FRAME_CNT = FT_BASE_ADR
34
+ FT_SONG_SPEED = FT_BASE_ADR+1
35
+ FT_INSTRUMENT_L = FT_BASE_ADR+2
36
+ FT_INSTRUMENT_H = FT_BASE_ADR+3
37
+ FT_PULSE1_PREV = FT_BASE_ADR+4
38
+ FT_PULSE2_PREV = FT_BASE_ADR+5
39
+ FT_CHANNELS = FT_BASE_ADR+6
40
+ FT_CH1_VARS = FT_CHANNELS
41
+ FT_CH2_VARS = FT_CHANNELS+9
42
+ FT_CH3_VARS = FT_CHANNELS+18
43
+ FT_CH4_VARS = FT_CHANNELS+27
44
+ FT_CH5_VARS = FT_CHANNELS+36
45
+ FT_ENVELOPES = FT_BASE_ADR+51
46
+ FT_CH1_ENVS = FT_ENVELOPES ;three envelopes (5*3 bytes) for pulse and triangle
47
+ FT_CH2_ENVS = FT_ENVELOPES+15
48
+ FT_CH3_ENVS = FT_ENVELOPES+30
49
+ FT_CH4_ENVS = FT_ENVELOPES+45 ;only two envelopes (5*2 bytes) for noise
50
+ FT_DPCM_TABLE_L = FT_BASE_ADR+106
51
+ FT_DPCM_TABLE_H = FT_BASE_ADR+107
52
+ FT_DPCM_EFFECT = FT_BASE_ADR+108
53
+ FT_SFX_ADR_L = FT_BASE_ADR+109
54
+ FT_SFX_ADR_H = FT_BASE_ADR+110
55
+ FT_PAL_ADJUST = FT_BASE_ADR+111
56
+
57
+ ;envelope variables offsets, every envelope uses 5 bytes
58
+
59
+ FT_ENV_STRUCT_SIZE = 5
60
+ FT_ENV_VALUE = FT_BASE_ADR+0
61
+ FT_ENV_REPEAT = FT_BASE_ADR+1
62
+ FT_ENV_ADR_L = FT_BASE_ADR+2
63
+ FT_ENV_ADR_H = FT_BASE_ADR+3
64
+ FT_ENV_PTR = FT_BASE_ADR+4
65
+
66
+ ;channels variables offsets, every channel uses 9 bytes
67
+
68
+ FT_CHN_STRUCT_SIZE = 9
69
+ FT_CHN_REPEAT = FT_BASE_ADR+0
70
+ FT_CHN_NOTE = FT_BASE_ADR+1
71
+ FT_CHN_INSTRUMENT = FT_BASE_ADR+2
72
+ FT_CHN_DUTY = FT_BASE_ADR+3
73
+ FT_CHN_PTR_L = FT_BASE_ADR+4
74
+ FT_CHN_PTR_H = FT_BASE_ADR+5
75
+ FT_CHN_RETURN_L = FT_BASE_ADR+6
76
+ FT_CHN_RETURN_H = FT_BASE_ADR+7
77
+ FT_CHN_REF_LEN = FT_BASE_ADR+8
78
+
79
+ ;aliases for outputs
80
+
81
+ FT_CH1_NOTE = FT_CH1_VARS+.lobyte(FT_CHN_NOTE)
82
+ FT_CH2_NOTE = FT_CH2_VARS+.lobyte(FT_CHN_NOTE)
83
+ FT_CH3_NOTE = FT_CH3_VARS+.lobyte(FT_CHN_NOTE)
84
+ FT_CH4_NOTE = FT_CH4_VARS+.lobyte(FT_CHN_NOTE)
85
+ FT_CH5_NOTE = FT_CH5_VARS+.lobyte(FT_CHN_NOTE)
86
+ FT_CH1_VOLUME = FT_CH1_ENVS+.lobyte(FT_ENV_VALUE)
87
+ FT_CH2_VOLUME = FT_CH2_ENVS+.lobyte(FT_ENV_VALUE)
88
+ FT_CH3_VOLUME = FT_CH3_ENVS+.lobyte(FT_ENV_VALUE)
89
+ FT_CH4_VOLUME = FT_CH4_ENVS+.lobyte(FT_ENV_VALUE)
90
+ FT_CH1_NOTE_OFF = FT_CH1_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE
91
+ FT_CH2_NOTE_OFF = FT_CH2_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE
92
+ FT_CH3_NOTE_OFF = FT_CH3_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE
93
+ FT_CH4_NOTE_OFF = FT_CH4_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE
94
+ FT_CH1_PITCH_OFF = FT_CH1_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE*2
95
+ FT_CH2_PITCH_OFF = FT_CH2_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE*2
96
+ FT_CH3_PITCH_OFF = FT_CH3_ENVS+.lobyte(FT_ENV_VALUE)+FT_ENV_STRUCT_SIZE*2
97
+ FT_CH1_DUTY = FT_CH1_VARS+.lobyte(FT_CHN_DUTY)
98
+ FT_CH2_DUTY = FT_CH2_VARS+.lobyte(FT_CHN_DUTY)
99
+ FT_CH3_DUTY = FT_CH3_VARS+.lobyte(FT_CHN_DUTY)
100
+ FT_CH4_DUTY = FT_CH4_VARS+.lobyte(FT_CHN_DUTY)
101
+
102
+ ;output buffer, used then sound effects are enabled
103
+
104
+ FT_OUT_BUF = FT_BASE_ADR+112 ;11 bytes
105
+
106
+ ;aliases for APU registers for music FamiTone
107
+
108
+ .if(!FT_SFX_ENABLE) ;if sound effects are disabled, just write to APU
109
+ FT_MR_PULSE1_V = APU_PL1_VOL
110
+ FT_MR_PULSE1_L = APU_PL1_LO
111
+ FT_MR_PULSE1_H = APU_PL1_HI
112
+ FT_MR_PULSE2_V = APU_PL2_VOL
113
+ FT_MR_PULSE2_L = APU_PL2_LO
114
+ FT_MR_PULSE2_H = APU_PL2_HI
115
+ FT_MR_TRI_V = APU_TRI_LINEAR
116
+ FT_MR_TRI_L = APU_TRI_LO
117
+ FT_MR_TRI_H = APU_TRI_HI
118
+ FT_MR_NOISE_V = APU_NOISE_VOL
119
+ FT_MR_NOISE_F = APU_NOISE_LO
120
+ .else ;otherwise write to output buffer
121
+ FT_MR_PULSE1_V = FT_OUT_BUF
122
+ FT_MR_PULSE1_L = FT_OUT_BUF+1
123
+ FT_MR_PULSE1_H = FT_OUT_BUF+2
124
+ FT_MR_PULSE2_V = FT_OUT_BUF+3
125
+ FT_MR_PULSE2_L = FT_OUT_BUF+4
126
+ FT_MR_PULSE2_H = FT_OUT_BUF+5
127
+ FT_MR_TRI_V = FT_OUT_BUF+6
128
+ FT_MR_TRI_L = FT_OUT_BUF+7
129
+ FT_MR_TRI_H = FT_OUT_BUF+8
130
+ FT_MR_NOISE_V = FT_OUT_BUF+9
131
+ FT_MR_NOISE_F = FT_OUT_BUF+10
132
+ .endif
133
+
134
+ ;sound effect stream variables, 15 bytes per stream
135
+
136
+ FT_SFX_BASE_ADR = FT_BASE_ADR+123
137
+
138
+ FT_SFX_STRUCT_SIZE = 15
139
+ FT_SFX_REPEAT = FT_SFX_BASE_ADR
140
+ FT_SFX_PTR_L = FT_SFX_BASE_ADR+1
141
+ FT_SFX_PTR_H = FT_SFX_BASE_ADR+2
142
+ FT_SFX_OFF = FT_SFX_BASE_ADR+3
143
+ FT_SFX_BUF = FT_SFX_BASE_ADR+4 ;11 bytes
144
+
145
+ ;aliases for channels to use in user calls
146
+
147
+ FT_SFX_CH0 = 0
148
+ FT_SFX_CH1 = FT_SFX_STRUCT_SIZE
149
+ FT_SFX_CH2 = FT_SFX_STRUCT_SIZE*2
150
+ FT_SFX_CH3 = FT_SFX_STRUCT_SIZE*3
151
+
152
+
153
+
154
+ ;reset APU, initialize FamiTone
155
+ ;in: A 0 for PAL, not 0 for NTSC
156
+
157
+ FamiToneInit:
158
+ cmp #0
159
+ beq @pal
160
+ lda #$ff
161
+ @pal:
162
+ sta FT_PAL_ADJUST
163
+ lda #$0f ;enable channels, stop DMC
164
+ sta APU_SND_CHN
165
+ lda #$81 ;disable triangle length counter
166
+ sta APU_TRI_LINEAR
167
+ lda #$01 ;load noise length
168
+ sta APU_NOISE_HI
169
+
170
+ lda #$30 ;volumes to 0
171
+ sta APU_PL1_VOL
172
+ sta APU_PL2_VOL
173
+ sta APU_NOISE_VOL
174
+ lda #$08 ;no sweep
175
+ sta APU_PL1_SWEEP
176
+ sta APU_PL2_SWEEP
177
+
178
+ lda #$ff
179
+ sta FT_PULSE1_PREV
180
+ sta FT_PULSE2_PREV
181
+
182
+
183
+
184
+ ;stop music that currently plays (it is a part of FamiToneInit as well)
185
+
186
+ FamiToneMusicStop:
187
+ ldx #.lobyte(FT_CHANNELS) ;reset all the channels variables
188
+ ldy #5
189
+ @setChannels:
190
+ lda #0
191
+ sta FT_CHN_PTR_L,x
192
+ sta FT_CHN_PTR_H,x
193
+ sta FT_CHN_REPEAT,x
194
+ sta FT_CHN_REF_LEN,x
195
+ sta FT_CHN_INSTRUMENT,x
196
+ lda #63
197
+ sta FT_CHN_NOTE,x
198
+ lda #$30
199
+ sta FT_CHN_DUTY,x
200
+ txa
201
+ clc
202
+ adc #FT_CHN_STRUCT_SIZE
203
+ tax
204
+ dey
205
+ bne @setChannels
206
+
207
+ sty FT_CH1_VOLUME ;reset volumes
208
+ sty FT_CH2_VOLUME
209
+ sty FT_CH3_VOLUME
210
+ sty FT_CH4_VOLUME
211
+ sty FT_DPCM_EFFECT ;no DPCM effect playing
212
+ sty FT_SONG_SPEED ;no music playing
213
+
214
+ rts
215
+
216
+
217
+
218
+ ;start playing a music
219
+ ;in: X,Y address of the module (LSB,MSB)
220
+
221
+ FamiToneMusicStart:
222
+ lda #0
223
+ sta FT_SONG_SPEED ;stop music update
224
+ stx <FT_TEMP
225
+ sty <FT_TEMP+1
226
+ tay ;A=0
227
+
228
+ ldx FT_PAL_ADJUST
229
+ bmi @noSetAdjust
230
+ sta FT_PAL_ADJUST
231
+ @noSetAdjust:
232
+
233
+ ldx #.lobyte(FT_CHANNELS)
234
+ lda #5
235
+ sta FT_TEMP+2
236
+ @setChannels:
237
+ lda (FT_TEMP),y
238
+ sta FT_CHN_PTR_L,x
239
+ iny
240
+ lda (FT_TEMP),y
241
+ sta FT_CHN_PTR_H,x
242
+ iny
243
+
244
+ lda #0
245
+ sta FT_CHN_REPEAT,x
246
+ sta FT_CHN_REF_LEN,x
247
+ sta FT_CHN_INSTRUMENT,x
248
+ lda #63
249
+ sta FT_CHN_NOTE,x
250
+ lda #$30
251
+ sta FT_CHN_DUTY,x
252
+
253
+ txa
254
+ clc
255
+ adc #FT_CHN_STRUCT_SIZE
256
+ tax
257
+ dec <FT_TEMP+2
258
+ bne @setChannels
259
+
260
+ lda (FT_TEMP),y
261
+ iny
262
+ sta FT_INSTRUMENT_L
263
+ lda (FT_TEMP),y
264
+ iny
265
+ sta FT_INSTRUMENT_H
266
+
267
+ lda (FT_TEMP),y
268
+ pha
269
+
270
+ lda #4
271
+ sta <FT_TEMP+6
272
+ lda #.lobyte(FT_ENVELOPES)
273
+ @setEnvelopes:
274
+ pha
275
+ tax
276
+ lda #0
277
+ jsr setInstrument
278
+ pla
279
+ adc #FT_ENV_STRUCT_SIZE*3
280
+ dec <FT_TEMP+6
281
+ bne @setEnvelopes
282
+
283
+ pla
284
+ sta FT_SONG_SPEED ;this enables music update
285
+ sta FT_FRAME_CNT
286
+
287
+ rts
288
+
289
+
290
+
291
+ ;pause and unpause current music
292
+ ;in: A 0 or not 0 to play or pause
293
+
294
+ FamiToneMusicPause:
295
+ tax
296
+ lda FT_SONG_SPEED
297
+ cpx #0
298
+ beq @play
299
+ ora #$80
300
+ bne @set
301
+ @play:
302
+ and #$7f
303
+ @set:
304
+ sta FT_SONG_SPEED
305
+ rts
306
+
307
+
308
+ ;update FamiTone state, should be called every TV frame
309
+
310
+ FamiToneUpdate:
311
+ .if(FT_THREAD)
312
+ lda FT_TEMP
313
+ pha
314
+ lda FT_TEMP+1
315
+ pha
316
+ .endif
317
+
318
+ ldx FT_PAL_ADJUST ;for PAL mode count 0..4
319
+ bmi @noAdjust
320
+ inx
321
+ cpx #5
322
+ bne @noSkip
323
+ ldx #0
324
+ @noSkip:
325
+ stx FT_PAL_ADJUST
326
+ @noAdjust:
327
+
328
+ lda FT_SONG_SPEED
329
+ beq @noMusic
330
+ bmi @noMusic ;music paused
331
+
332
+ lda FT_FRAME_CNT ;check TV frame counter
333
+ beq @row ;if it is 0 or negative, it is a new row
334
+ bmi @row
335
+ bne @noRow
336
+ @row:
337
+
338
+ lda #.lobyte(FT_CHANNELS) ;start of a row, updating all the channels
339
+ sta <FT_TEMP+4
340
+ lda #.lobyte(FT_ENVELOPES)
341
+ sta <FT_TEMP+5
342
+ lda #4 ;process pulse, triangle, and noise channels
343
+ sta <FT_TEMP+6
344
+ ldy #0
345
+ @processChns:
346
+ ldx <FT_TEMP+4
347
+ jsr channelStep
348
+ bcs @noNewNote ;check if there was a new note
349
+ ldx <FT_TEMP+4 ;setting up a new note with current instrument
350
+ lda FT_CHN_INSTRUMENT,x
351
+ ldx <FT_TEMP+5
352
+ jsr setInstrument
353
+ ldx <FT_TEMP+4
354
+ sta FT_CHN_DUTY,x
355
+ @noNewNote:
356
+ lda <FT_TEMP+4 ;next channel
357
+ clc
358
+ adc #FT_CHN_STRUCT_SIZE
359
+ sta <FT_TEMP+4
360
+ lda <FT_TEMP+5 ;next envelopes block
361
+ clc
362
+ adc #FT_ENV_STRUCT_SIZE*3
363
+ sta <FT_TEMP+5
364
+ dec <FT_TEMP+6
365
+ bne @processChns
366
+
367
+ .if(FT_DPCM_ENABLE)
368
+
369
+ ldx #.lobyte(FT_CH5_VARS)
370
+ jsr channelStep
371
+ bcs @ch5done
372
+ cmp #63
373
+ bne @ch5note
374
+ jsr FamiToneSampleStop
375
+ jmp @ch5done
376
+ @ch5note:
377
+ lda FT_CH5_NOTE
378
+ jsr FamiToneSampleStartM
379
+ @ch5done:
380
+
381
+ .endif
382
+
383
+ lda FT_FRAME_CNT ;set TV frame counter
384
+ clc
385
+ adc FT_SONG_SPEED
386
+ sta FT_FRAME_CNT
387
+
388
+ @noRow:
389
+ lda #11 ;now process all the envelopes (11 because noise has no pitch)
390
+ sta <FT_TEMP+2
391
+ ldx #.lobyte(FT_ENVELOPES)
392
+ @processEnvs:
393
+ txa
394
+ pha
395
+ jsr envelopeStep
396
+ pla
397
+ clc
398
+ adc #FT_ENV_STRUCT_SIZE
399
+ tax
400
+ dec <FT_TEMP+2
401
+ bne @processEnvs
402
+
403
+ @noMusic:
404
+
405
+ lda FT_SONG_SPEED
406
+ bpl @noPause
407
+ lda #$30
408
+ sta FT_MR_PULSE1_V
409
+ sta FT_MR_PULSE2_V
410
+ sta FT_MR_NOISE_V
411
+ lda #$80
412
+ sta FT_MR_TRI_V
413
+ jmp @noSkipM
414
+ @noPause:
415
+
416
+ ;converting output values and sending them to the APU or into output buffer
417
+
418
+ lda FT_CH1_NOTE
419
+ cmp #63
420
+ bne @ch1note
421
+ lda #0
422
+ jmp @ch1cut
423
+ @ch1note:
424
+ clc
425
+ adc FT_CH1_NOTE_OFF
426
+ asl a
427
+ tax
428
+ lda FT_CH1_PITCH_OFF
429
+ pha
430
+ adc noteTable,x
431
+ sta FT_MR_PULSE1_L
432
+ pla
433
+ ora #$7f
434
+ bmi @ch1sign
435
+ lda #0
436
+ @ch1sign:
437
+ adc noteTable+1,x
438
+
439
+ .if(!FT_SFX_ENABLE)
440
+ cmp FT_PULSE1_PREV
441
+ beq @ch1prev
442
+ sta FT_PULSE1_PREV
443
+ .endif
444
+
445
+ sta FT_MR_PULSE1_H
446
+ @ch1prev:
447
+ lda FT_CH1_VOLUME
448
+ @ch1cut:
449
+ ora FT_CH1_DUTY
450
+ sta FT_MR_PULSE1_V
451
+
452
+ lda FT_CH2_NOTE
453
+ cmp #63
454
+ bne @ch2note
455
+ lda #0
456
+ jmp @ch2cut
457
+ @ch2note:
458
+ clc
459
+ adc FT_CH2_NOTE_OFF
460
+ asl a
461
+ tax
462
+ lda FT_CH2_PITCH_OFF
463
+ pha
464
+ adc noteTable,x
465
+ sta FT_MR_PULSE2_L
466
+ pla
467
+ ora #$7f
468
+ bmi @ch2sign
469
+ lda #0
470
+ @ch2sign:
471
+ adc noteTable+1,x
472
+
473
+ .if(!FT_SFX_ENABLE)
474
+ cmp FT_PULSE2_PREV
475
+ beq @ch2prev
476
+ sta FT_PULSE2_PREV
477
+ .endif
478
+
479
+ sta FT_MR_PULSE2_H
480
+ @ch2prev:
481
+ lda FT_CH2_VOLUME
482
+ @ch2cut:
483
+ ora FT_CH2_DUTY
484
+ sta FT_MR_PULSE2_V
485
+
486
+ lda FT_CH3_NOTE
487
+ cmp #63
488
+ bne @ch3note
489
+ lda #0
490
+ jmp @ch3cut
491
+ @ch3note:
492
+ clc
493
+ adc FT_CH3_NOTE_OFF
494
+ asl a
495
+ tax
496
+ lda FT_CH3_PITCH_OFF
497
+ pha
498
+ adc noteTable,x
499
+ sta FT_MR_TRI_L
500
+ pla
501
+ ora #$7f
502
+ bmi @ch3sign
503
+ lda #0
504
+ @ch3sign:
505
+ adc noteTable+1,x
506
+ sta FT_MR_TRI_H
507
+ lda FT_CH3_VOLUME
508
+ @ch3cut:
509
+ ora #$80
510
+ sta FT_MR_TRI_V
511
+
512
+ lda FT_CH4_NOTE
513
+ cmp #63
514
+ bne @ch4note
515
+ lda #0
516
+ jmp @ch4cut
517
+ @ch4note:
518
+ clc
519
+ adc FT_CH4_NOTE_OFF
520
+ and #$0f
521
+ eor #$0f
522
+ sta <FT_TEMP
523
+ lda FT_CH4_DUTY
524
+ asl a
525
+ and #$80
526
+ ora <FT_TEMP
527
+ sta FT_MR_NOISE_F
528
+ lda FT_CH4_VOLUME
529
+ @ch4cut:
530
+ ora #$f0
531
+ sta FT_MR_NOISE_V
532
+
533
+ dec FT_FRAME_CNT
534
+ lda FT_PAL_ADJUST ;for PAL mode decrease row length every fifth frame
535
+ bne @noSkipM
536
+ dec FT_FRAME_CNT
537
+ @noSkipM:
538
+
539
+ .if(FT_SFX_ENABLE)
540
+
541
+ ldx #FT_SFX_CH0 ;process all the sound effects streams
542
+ lda #FT_SFX_STREAMS
543
+ sta <FT_TEMP+3
544
+ @updateSfxChannels:
545
+ jsr FamiToneSfxUpdate
546
+ txa
547
+ clc
548
+ adc #FT_SFX_STRUCT_SIZE
549
+ tax
550
+ dec <FT_TEMP+3
551
+ bne @updateSfxChannels
552
+
553
+ lda FT_OUT_BUF ;now send data from output buffer to the APU
554
+ sta APU_PL1_VOL
555
+ lda FT_OUT_BUF+1
556
+ sta APU_PL1_LO
557
+ lda FT_OUT_BUF+2
558
+ cmp FT_PULSE1_PREV
559
+ beq @noUpdatePulse1
560
+ sta FT_PULSE1_PREV
561
+ sta APU_PL1_HI
562
+ @noUpdatePulse1:
563
+ lda FT_OUT_BUF+3
564
+ sta APU_PL2_VOL
565
+ lda FT_OUT_BUF+4
566
+ sta APU_PL2_LO
567
+ lda FT_OUT_BUF+5
568
+ cmp FT_PULSE2_PREV
569
+ beq @noUpdatePulse2
570
+ sta FT_PULSE2_PREV
571
+ sta APU_PL2_HI
572
+ @noUpdatePulse2:
573
+ lda FT_OUT_BUF+6
574
+ sta APU_TRI_LINEAR
575
+ lda FT_OUT_BUF+7
576
+ sta APU_TRI_LO
577
+ lda FT_OUT_BUF+8
578
+ sta APU_TRI_HI
579
+
580
+ lda FT_OUT_BUF+9
581
+ sta APU_NOISE_VOL
582
+ lda FT_OUT_BUF+10
583
+ sta APU_NOISE_LO
584
+
585
+ .endif
586
+
587
+ .if(FT_THREAD)
588
+ pla
589
+ sta FT_TEMP+1
590
+ pla
591
+ sta FT_TEMP
592
+ .endif
593
+
594
+ rts
595
+
596
+
597
+
598
+ ;set envelopes of an instrument
599
+ ;in: A instrument number 0..31
600
+ ; X is offset of block of envelopes in the FamiTone's RAM page
601
+ ;out: Y 0
602
+
603
+ setInstrument:
604
+ asl a ;A*8, every instrument takes 8 bytes
605
+ asl a
606
+ asl a
607
+ clc
608
+ adc FT_INSTRUMENT_L ;get instrument address into FT_TEMP
609
+ sta <FT_TEMP
610
+ lda #0
611
+ adc FT_INSTRUMENT_H
612
+ sta <FT_TEMP+1
613
+
614
+ lda #3 ;three envelopes for pulse and triangle channels
615
+ cpx #.lobyte(FT_CH4_ENVS)
616
+ bne @noNoise
617
+ lda #2 ;only two envelopes for noise, no pitch
618
+ @noNoise:
619
+ sta <FT_TEMP+2
620
+
621
+ ldy #0
622
+ clc
623
+ @loop:
624
+ lda (FT_TEMP),y ;get LSB of an envelope
625
+ sta FT_ENV_ADR_L,x
626
+ iny
627
+ lda (FT_TEMP),y ;get MSB
628
+ sta FT_ENV_ADR_H,x
629
+ iny
630
+ lda #0
631
+ sta FT_ENV_REPEAT,x ;reset repeat counter
632
+ sta FT_ENV_PTR,x ;reset envelope pointer
633
+ txa
634
+ adc #FT_ENV_STRUCT_SIZE
635
+ tax
636
+ dec <FT_TEMP+2
637
+ bne @loop
638
+
639
+ ldy #6
640
+ lda (FT_TEMP),y ;duty cycle
641
+ ldy #0
642
+ rts
643
+
644
+
645
+
646
+ ;process channel
647
+ ;in: X is offset of channel variables in the FamiTone's RAM page
648
+ ; Y 0
649
+ ;out: Carry is reset if the was new note
650
+
651
+ channelStep:
652
+ lda FT_CHN_REF_LEN,x ;check reference rows counter
653
+ beq @noRef ;if it is zero, there is no reference
654
+ dec FT_CHN_REF_LEN,x ;decrease rows counter
655
+ bne @noRef
656
+ lda FT_CHN_RETURN_L,x ;end of reference, return to previous pointer
657
+ sta <FT_TEMP
658
+ lda FT_CHN_RETURN_H,x
659
+ sta <FT_TEMP+1
660
+ jmp @noRepeatR
661
+ @noRef:
662
+ lda FT_CHN_REPEAT,x ;check pause counter
663
+ beq @noRepeat
664
+ dec FT_CHN_REPEAT,x ;decrease pause counter
665
+ sec ;no new note
666
+ rts
667
+ @noRepeat:
668
+ lda FT_CHN_PTR_L,x ;load channel pointer into temp
669
+ sta <FT_TEMP
670
+ lda FT_CHN_PTR_H,x
671
+ sta <FT_TEMP+1
672
+ @noRepeatR:
673
+
674
+ @readByte:
675
+ lda (FT_TEMP),y ;read byte of the channel
676
+ inc <FT_TEMP ;increase pointer
677
+ bne @1
678
+ inc <FT_TEMP+1
679
+ @1:
680
+ cmp #%01000000 ;if bits 7 or 6 are set, it is instrument, tag, or effect
681
+ bcs @special
682
+ sta FT_CHN_NOTE,x ;remember note code
683
+
684
+ @return:
685
+ lda <FT_TEMP ;store pointer from temp to the variable
686
+ sta FT_CHN_PTR_L,x
687
+ lda <FT_TEMP+1
688
+ sta FT_CHN_PTR_H,x
689
+ rts
690
+
691
+ @special:
692
+ cmp #%11000000 ;check if it is special tag
693
+ bcs @noInstr
694
+ cmp #%10000000 ;check if it is instrument
695
+ bcc @noPause
696
+ and #$3f
697
+ sta FT_CHN_REPEAT,x ;set up pause counter
698
+ jmp @return ;no new note, because Carry is set
699
+
700
+ @noPause:
701
+ and #$3f
702
+ sta FT_CHN_INSTRUMENT,x ;remember instrument number
703
+ jmp @readByte ;and read next byte
704
+
705
+ @noInstr:
706
+ cmp #%11111111 ;check if it is reference
707
+ bne @noEof
708
+ clc ;remember return address+3
709
+ lda <FT_TEMP
710
+ adc #3
711
+ sta FT_CHN_RETURN_L,x
712
+ lda <FT_TEMP+1
713
+ adc #0
714
+ sta FT_CHN_RETURN_H,x
715
+ lda (FT_TEMP),y ;read length of the reference (how many rows)
716
+ sta FT_CHN_REF_LEN,x
717
+ iny
718
+ lda (FT_TEMP),y ;read 16-bit absolute address of the reference
719
+ sta <FT_TEMP+2 ;remember in temp
720
+ iny
721
+ lda (FT_TEMP),y
722
+ sta <FT_TEMP+1
723
+ lda <FT_TEMP+2
724
+ sta <FT_TEMP
725
+ ldy #0
726
+ jmp @readByte ;and read next byte
727
+
728
+ @noEof:
729
+ cmp #%11111110 ;check if it is end of the channel
730
+ bne @effect
731
+ lda (FT_TEMP),y ;read two next bytes
732
+ sta <FT_TEMP+2
733
+ iny
734
+ lda (FT_TEMP),y
735
+ dey
736
+ sta <FT_TEMP+1 ;and set current pointer
737
+ lda <FT_TEMP+2
738
+ sta <FT_TEMP
739
+ jmp @readByte ;and read next byte
740
+
741
+ @effect:
742
+ and #$3f ;speed change
743
+ sta FT_SONG_SPEED
744
+ jmp @readByte
745
+
746
+
747
+
748
+ ;process an envelope
749
+ ;it does not matter which type an envelope is
750
+ ;in: X offset of the envelope variables in the FamiTone's RAM page
751
+
752
+ envelopeStep:
753
+ lda FT_ENV_REPEAT,x ;check envelope repeat counter
754
+ beq @noRepeat ;if it is zero, process the envelope
755
+ dec FT_ENV_REPEAT,x ;otherwise decrement the counter
756
+ rts
757
+ @noRepeat:
758
+ lda FT_ENV_ADR_L,x ;load envelope address into temp
759
+ sta <FT_TEMP
760
+ lda FT_ENV_ADR_H,x
761
+ sta <FT_TEMP+1
762
+ ldy FT_ENV_PTR,x ;load envelope pointer
763
+
764
+ @readByte:
765
+ lda (FT_TEMP),y ;read byte of the envelope
766
+ iny ;increase pointer
767
+ ora #0
768
+ bpl @special ;if it is below 127, it is special code
769
+ clc ;otherwise it is an output value+192
770
+ adc #256-192
771
+ sta FT_ENV_VALUE,x
772
+ tya
773
+ sta FT_ENV_PTR,x ;remember the pointer and return
774
+ rts
775
+ @special:
776
+ cmp #127 ;if it is 127, it is end of an envelope
777
+ beq @loop
778
+ sta FT_ENV_REPEAT,x ;otherwise it is a value for repeat counter
779
+ tya
780
+ sta FT_ENV_PTR,x ;remember the value and return
781
+ rts
782
+ @loop:
783
+ lda (FT_TEMP),y ;load loop pointer
784
+ tay
785
+ jmp @readByte ;and read next byte
786
+
787
+
788
+ .if(FT_DPCM_ENABLE)
789
+
790
+ ;set sample table pointer, only needed if DMC is used
791
+ ;in: X,Y is address of a table that holds parameters for 12 samples
792
+
793
+ FamiToneSampleInit:
794
+ stx FT_DPCM_TABLE_L
795
+ sty FT_DPCM_TABLE_H
796
+ rts
797
+
798
+
799
+
800
+ ;stop DMC sample if it plays
801
+
802
+ FamiToneSampleStop:
803
+ lda #%00001111
804
+ sta APU_SND_CHN
805
+ rts
806
+
807
+
808
+
809
+ ;play DMC sample from table, used by music player and could be used externally
810
+ ;in: A is number of sample, 0..11
811
+
812
+ FamiToneSampleStartM: ;for music (low priority)
813
+ ldx FT_DPCM_EFFECT
814
+ beq FamiToneSampleStartS
815
+ tax
816
+ lda APU_SND_CHN
817
+ and #16
818
+ beq @noEffect
819
+ rts
820
+ @noEffect:
821
+ sta FT_DPCM_EFFECT
822
+ txa
823
+ jmp FamiToneSampleStartS
824
+
825
+ FamiToneSampleStart: ;for sound effects (high priority)
826
+ ldx #1
827
+ stx FT_DPCM_EFFECT
828
+
829
+ FamiToneSampleStartS:
830
+ asl a ;get address in sample table
831
+ asl a
832
+ adc FT_DPCM_TABLE_L
833
+ sta <FT_TEMP
834
+ lda #0
835
+ adc FT_DPCM_TABLE_H
836
+ sta <FT_TEMP+1
837
+
838
+ lda #%00001111 ;stop DMC
839
+ sta APU_SND_CHN
840
+
841
+ ldy #0
842
+ lda (FT_TEMP),y ;sample offset
843
+ sta APU_DMC_START
844
+ iny
845
+ lda (FT_TEMP),y ;sample length
846
+ sta APU_DMC_LEN
847
+ iny
848
+ lda (FT_TEMP),y ;pitch and loop
849
+ sta APU_DMC_FREQ
850
+
851
+ lda #32 ;reset DAC counter
852
+ sta APU_DMC_RAW
853
+ lda #%00011111 ;start DMC
854
+ sta APU_SND_CHN
855
+
856
+ rts
857
+
858
+ .endif
859
+
860
+
861
+
862
+ .if(FT_SFX_ENABLE)
863
+
864
+ ;init sound effects player, set pointer to data
865
+ ;in: X,Y is address of sound effects data
866
+
867
+ FamiToneSfxInit:
868
+ stx FT_SFX_ADR_L ;remember pointer to the data
869
+ sty FT_SFX_ADR_H
870
+ ldx #FT_SFX_CH0 ;init all the streams
871
+ ldy #FT_SFX_STREAMS
872
+ @1:
873
+ lda #0
874
+ sta FT_SFX_REPEAT,x
875
+ sta FT_SFX_PTR_H,x
876
+ jsr FamiToneSfxClearBuf
877
+ txa
878
+ clc
879
+ adc #FT_SFX_STRUCT_SIZE
880
+ tax
881
+ dey
882
+ bne @1
883
+
884
+ rts
885
+
886
+
887
+
888
+ ;play a sound effect
889
+ ;in: A is a number of the sound effect
890
+ ; X is offset of sound effect stream, should be FT_SFX_CH0..FT_SFX_CH3
891
+
892
+ FamiToneSfxStart:
893
+ asl a ;get address in effects list
894
+ tay
895
+ lda #0
896
+ sta FT_SFX_PTR_H,x ;this stops the effect
897
+ sta FT_SFX_REPEAT,x ;reset repeat counter and pointer offset
898
+ sta FT_SFX_OFF,x
899
+ jsr FamiToneSfxClearBuf
900
+ lda FT_SFX_ADR_L
901
+ sta <FT_TEMP
902
+ lda FT_SFX_ADR_H
903
+ sta <FT_TEMP+1
904
+ lda (FT_TEMP),y ;read effect pointer from the table
905
+ sta FT_SFX_PTR_L,x ;and remember it
906
+ iny
907
+ lda (FT_TEMP),y
908
+ sta FT_SFX_PTR_H,x ;this enables the effect
909
+ rts
910
+
911
+
912
+
913
+ ;clear output buffer of a sound effect
914
+ ;in: A is 0
915
+ ; X is offset of sound effect stream
916
+
917
+ FamiToneSfxClearBuf:
918
+ sta FT_SFX_BUF+6,x
919
+ lda #$30
920
+ sta FT_SFX_BUF,x
921
+ sta FT_SFX_BUF+3,x
922
+ sta FT_SFX_BUF+9,x
923
+ rts
924
+
925
+
926
+
927
+ ;update one sound effect stream
928
+ ;in: X is offset of sound effect stream
929
+
930
+ FamiToneSfxUpdate:
931
+ lda FT_SFX_REPEAT,x ;check if repeat counter is not zero
932
+ beq @noRepeat
933
+ dec FT_SFX_REPEAT,x ;decrement and return
934
+ jmp @updateBuf ;just mix with output buffer
935
+ @noRepeat:
936
+ lda FT_SFX_PTR_H,x ;check if MSB of pointer is not zero
937
+ bne @sfxActive
938
+ rts ;return otherwise, no active effect
939
+ @sfxActive:
940
+ sta <FT_TEMP+1 ;load effect pointer into temp
941
+ lda FT_SFX_PTR_L,x
942
+ sta <FT_TEMP
943
+ ldy FT_SFX_OFF,x
944
+ @readByte:
945
+ lda (FT_TEMP),y ;read byte of effect
946
+ iny
947
+ cmp #$10 ;if it is less than $10, it is register write
948
+ bcc @getData
949
+ cmp #$ff ;if it is $ff, it is end of the effect
950
+ bcs @eof
951
+ adc #256-$10 ;otherwise it is number of repeats +$10
952
+ sta FT_SFX_REPEAT,x
953
+ tya
954
+ sta FT_SFX_OFF,x
955
+ jmp @updateBuf
956
+ @eof:
957
+ lda #0
958
+ sta FT_SFX_PTR_H,x
959
+ jmp @updateBuf
960
+ @getData:
961
+ stx <FT_TEMP+2 ;it is register write
962
+ adc <FT_TEMP+2 ;get offset in the effect output buffer
963
+ tax
964
+ lda (FT_TEMP),y ;read value
965
+ iny
966
+ sta FT_SFX_BUF,x ;store into output buffer
967
+ ldx <FT_TEMP+2
968
+ jmp @readByte ;and read next byte
969
+
970
+ @updateBuf:
971
+ lda FT_OUT_BUF ;now compare effect output buffer with main output buffer
972
+ and #$0f ;if volume of pulse 1 of effect is higher than of main buffer
973
+ sta <FT_TEMP ;overwrite pulse 1 of main buffer with one from effect buffer
974
+ lda FT_SFX_BUF,x
975
+ and #$0f
976
+ cmp <FT_TEMP
977
+ bcc @noPulse1
978
+ lda FT_SFX_BUF,x
979
+ sta FT_OUT_BUF
980
+ lda FT_SFX_BUF+1,x
981
+ sta FT_OUT_BUF+1
982
+ lda FT_SFX_BUF+2,x
983
+ sta FT_OUT_BUF+2
984
+ @noPulse1:
985
+ lda FT_OUT_BUF+3 ;same for pulse 2
986
+ and #$0f
987
+ sta <FT_TEMP
988
+ lda FT_SFX_BUF+3,x
989
+ and #$0f
990
+ cmp <FT_TEMP
991
+ bcc @noPulse2
992
+ lda FT_SFX_BUF+3,x
993
+ sta FT_OUT_BUF+3
994
+ lda FT_SFX_BUF+4,x
995
+ sta FT_OUT_BUF+4
996
+ lda FT_SFX_BUF+5,x
997
+ sta FT_OUT_BUF+5
998
+ @noPulse2:
999
+ lda FT_SFX_BUF+6,x ;overwrite triangle of main output buffer if it is active
1000
+ beq @noTriangle
1001
+ sta FT_OUT_BUF+6
1002
+ lda FT_SFX_BUF+7,x
1003
+ sta FT_OUT_BUF+7
1004
+ lda FT_SFX_BUF+8,x
1005
+ sta FT_OUT_BUF+8
1006
+ @noTriangle:
1007
+ lda FT_SFX_BUF+9,x ;same as for pulse 1 and 2, but for noise
1008
+ and #$0f
1009
+ sta <FT_TEMP
1010
+ lda FT_OUT_BUF+9
1011
+ and #$0f
1012
+ cmp <FT_TEMP
1013
+ bcs @noNoise
1014
+ lda FT_SFX_BUF+9,x
1015
+ sta FT_OUT_BUF+9
1016
+ lda FT_SFX_BUF+10,x
1017
+ sta FT_OUT_BUF+10
1018
+ @noNoise:
1019
+ rts
1020
+
1021
+ .endif
1022
+
1023
+
1024
+
1025
+ noteTable: ;NTSC, 11-bit dividers, octaves 1-5
1026
+ .word $6ad,$64d,$5f2,$59d,$54c,$500,$4b8,$474,$434,$3f7,$3be,$388
1027
+ .word $356,$326,$2f8,$2ce,$2a5,$27f,$25b,$239,$219,$1fb,$1de,$1c3
1028
+ .word $1aa,$192,$17b,$166,$152,$13f,$12d,$11c,$10c,$0fd,$0ee,$0e1
1029
+ .word $0d4,$0c8,$0bd,$0b2,$0a8,$09f,$096,$08d,$085,$07e,$076,$070
1030
+ .word $069,$063,$05e,$058,$053,$04f,$04a,$046,$042,$03e,$03a,$037
1031
+ .word 0,0,0,0