romdevtools 0.71.0 → 0.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +19 -16
- package/CHANGELOG.md +196 -0
- package/README.md +5 -5
- package/examples/README.md +1 -0
- package/examples/gametank/templates/gt_draw.h +91 -0
- package/examples/gametank/templates/gt_hud.h +89 -0
- package/examples/gametank/templates/gt_palette.h +59 -0
- package/examples/gametank/templates/gt_sound.h +90 -0
- package/examples/gametank/templates/gt_sprites.h +53 -0
- package/examples/gametank/templates/platformer.c +318 -0
- package/examples/gametank/templates/puzzle.c +295 -0
- package/examples/gametank/templates/racing.c +139 -0
- package/examples/gametank/templates/shmup.c +277 -0
- package/examples/gametank/templates/sports.c +119 -0
- package/package.json +23 -22
- package/src/cores/capabilities.js +24 -0
- package/src/cores/registry.js +7 -1
- package/src/host/LibretroHost.js +90 -17
- package/src/host/callbacks.js +20 -2
- package/src/host/cpu-state.js +17 -0
- package/src/host/gametank-acp-state.js +53 -0
- package/src/http/skill-doc.js +10 -6
- package/src/mcp/tools/audio.js +1 -1
- package/src/mcp/tools/cart-parts.js +76 -0
- package/src/mcp/tools/lifecycle.js +1 -1
- package/src/mcp/tools/platform-tools.js +9 -1
- package/src/mcp/tools/platforms.js +46 -10
- package/src/mcp/tools/toolchain.js +35 -10
- package/src/platforms/gametank/lib/gt/audio/acp_image.bin +0 -0
- package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.c +55 -0
- package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.h +34 -0
- package/src/platforms/gametank/lib/gt/audio/audio_fw.asm +223 -0
- package/src/platforms/gametank/lib/gt/audio/audio_fw_blob.s +8 -0
- package/src/platforms/gametank/lib/gt/audio/instruments.c +79 -0
- package/src/platforms/gametank/lib/gt/audio/instruments.h +25 -0
- package/src/platforms/gametank/lib/gt/audio/music.c +370 -0
- package/src/platforms/gametank/lib/gt/audio/music.h +35 -0
- package/src/platforms/gametank/lib/gt/audio/note_numbers.h +132 -0
- package/src/platforms/gametank/lib/gt/audio/scaled_sines.raw +0 -0
- package/src/platforms/gametank/lib/gt/audio/sine_256_-63_63.bin +0 -0
- package/src/platforms/gametank/lib/gt/banking.c +29 -0
- package/src/platforms/gametank/lib/gt/banking.h +8 -0
- package/src/platforms/gametank/lib/gt/banking2.s +41 -0
- package/src/platforms/gametank/lib/gt/crt0.s +102 -0
- package/src/platforms/gametank/lib/gt/draw_logo.s +55 -0
- package/src/platforms/gametank/lib/gt/feature/persist/persist.c +103 -0
- package/src/platforms/gametank/lib/gt/feature/persist/persist.h +13 -0
- package/src/platforms/gametank/lib/gt/feature/random/random.c +40 -0
- package/src/platforms/gametank/lib/gt/feature/random/random.h +18 -0
- package/src/platforms/gametank/lib/gt/feature/text/text.c +111 -0
- package/src/platforms/gametank/lib/gt/feature/text/text.h +25 -0
- package/src/platforms/gametank/lib/gt/gametank.c +12 -0
- package/src/platforms/gametank/lib/gt/gametank.h +80 -0
- package/src/platforms/gametank/lib/gt/gametank_logo.inc +393 -0
- package/src/platforms/gametank/lib/gt/gen/assets/assets_index.h +9 -0
- package/src/platforms/gametank/lib/gt/gen/assets/sdk_default.h +5 -0
- package/src/platforms/gametank/lib/gt/gen/bank_nums.h +11 -0
- package/src/platforms/gametank/lib/gt/gen/modules_enabled.h +4 -0
- package/src/platforms/gametank/lib/gt/gen/modules_enabled.inc +4 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_direct.c +132 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_direct.h +75 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_queue.c +177 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_queue.h +35 -0
- package/src/platforms/gametank/lib/gt/gfx/draw_util.s +157 -0
- package/src/platforms/gametank/lib/gt/gfx/gfx_sys.c +43 -0
- package/src/platforms/gametank/lib/gt/gfx/gfx_sys.h +46 -0
- package/src/platforms/gametank/lib/gt/gfx/sprites.c +216 -0
- package/src/platforms/gametank/lib/gt/gfx/sprites.h +41 -0
- package/src/platforms/gametank/lib/gt/init.c +9 -0
- package/src/platforms/gametank/lib/gt/input.c +26 -0
- package/src/platforms/gametank/lib/gt/input.h +20 -0
- package/src/platforms/gametank/lib/gt/interrupt.s +67 -0
- package/src/platforms/gametank/lib/gt/vectors.s +14 -0
- package/src/platforms/gametank/lib/gt/wait.s +53 -0
- package/src/platforms/gba/MENTAL_MODEL.md +22 -1
- package/src/playtest/playtest.js +174 -26
- package/src/playtest/resampler/build.sh +19 -0
- package/src/playtest/resampler/index.mjs +75 -0
- package/src/playtest/resampler/resampler.c +129 -0
- package/src/playtest/resampler/resampler.mjs +2 -0
- package/src/playtest/resampler/resampler.wasm +0 -0
- package/src/toolchains/arm-none-eabi-gcc/gcc.js +39 -188
- package/src/toolchains/asar/asar.js +10 -15
- package/src/toolchains/cc65/cc65.js +82 -92
- package/src/toolchains/cc65/da65.js +12 -17
- package/src/toolchains/cc65/preset-resolver.js +13 -2
- package/src/toolchains/cc65/presets/gametank/gametank.h +80 -0
- package/src/toolchains/cc65/presets/gametank/sdk.cfg +32 -0
- package/src/toolchains/cc65/presets/gametank/sdk.crt0.s +61 -0
- package/src/toolchains/cc65/presets/gametank/sdk.vectors.s +11 -0
- package/src/toolchains/cc65/presets/gametank/single-bank.cfg +28 -0
- package/src/toolchains/cc65/presets/gametank/single-bank.crt0.s +71 -0
- package/src/toolchains/cc65/presets/gametank/single-bank.vectors.s +12 -0
- package/src/toolchains/common/c-build.js +109 -0
- package/src/toolchains/common/gcc-toolchain.js +164 -0
- package/src/toolchains/common/wasm-tool.js +101 -0
- package/src/toolchains/dasm/dasm.js +12 -18
- package/src/toolchains/gba-c/gba-c.js +253 -305
- package/src/toolchains/genesis-c/genesis-c.js +196 -225
- package/src/toolchains/index.js +58 -4
- package/src/toolchains/m68k-elf-gcc/gcc.js +39 -202
- package/src/toolchains/mips-c/mips-c.js +68 -78
- package/src/toolchains/mips-elf-gcc/gcc.js +55 -118
- package/src/toolchains/rgbds/rgbds.js +7 -19
- package/src/toolchains/sdcc/sdcc.js +35 -26
- package/src/toolchains/sh-c/sh-c.js +44 -52
- package/src/toolchains/sh-elf-gcc/gcc.js +55 -110
- package/src/toolchains/sjasm/sjasm.js +10 -14
- package/src/toolchains/snes-c/snes-c.js +125 -150
- package/src/toolchains/tcc816/tcc816.js +10 -15
- package/src/toolchains/vasm68k/vasm68k.js +11 -16
- package/src/toolchains/wladx/wladx.js +5 -17
- package/src/toolchains/z80/binutils.js +5 -11
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
#include "music.h"
|
|
2
|
+
#include "gametank.h"
|
|
3
|
+
#include "note_numbers.h"
|
|
4
|
+
#include "banking.h"
|
|
5
|
+
|
|
6
|
+
#include "bank_nums.h"
|
|
7
|
+
#include "assets_index.h"
|
|
8
|
+
|
|
9
|
+
typedef struct music_state_t {
|
|
10
|
+
const unsigned char* cursor;
|
|
11
|
+
unsigned char bank;
|
|
12
|
+
unsigned char cfg; //file flags
|
|
13
|
+
unsigned char delay;
|
|
14
|
+
const unsigned char* repeat_ptr;
|
|
15
|
+
unsigned char flags; //playback flags
|
|
16
|
+
const Instrument* instruments[NUM_FM_CHANNELS];
|
|
17
|
+
} music_state_t;
|
|
18
|
+
|
|
19
|
+
#define MUSIC_STACK_SIZE 8
|
|
20
|
+
|
|
21
|
+
music_state_t music_state;
|
|
22
|
+
music_state_t music_stack[MUSIC_STACK_SIZE];
|
|
23
|
+
unsigned char music_stack_idx = 0;
|
|
24
|
+
|
|
25
|
+
void push_song_stack() {
|
|
26
|
+
music_stack[music_stack_idx++] = music_state;
|
|
27
|
+
if(music_stack_idx == MUSIC_STACK_SIZE) { music_stack_idx = 0; }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void pop_song_stack() {
|
|
31
|
+
if(music_stack_idx == 0) {
|
|
32
|
+
music_stack_idx = MUSIC_STACK_SIZE-1;
|
|
33
|
+
} else {
|
|
34
|
+
--music_stack_idx;
|
|
35
|
+
}
|
|
36
|
+
music_state = music_stack[music_stack_idx];
|
|
37
|
+
load_instrument(0, music_state.instruments[0]);
|
|
38
|
+
load_instrument(0, music_state.instruments[1]);
|
|
39
|
+
load_instrument(0, music_state.instruments[2]);
|
|
40
|
+
load_instrument(0, music_state.instruments[3]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
unsigned char channel_masks[NUM_FM_CHANNELS] = {1, 2, 4, 8};
|
|
44
|
+
signed char channel_note_offset[NUM_FM_CHANNELS] = {0, 0, 0, 0};
|
|
45
|
+
unsigned char audio_amplitudes[NUM_FM_OPS] = { 0, 0, 0, 0,
|
|
46
|
+
0, 0, 0, 0,
|
|
47
|
+
0, 0, 0, 0,
|
|
48
|
+
0, 0, 0, 0 };
|
|
49
|
+
unsigned char env_initial[NUM_FM_OPS] = { 0x00, 0x00, 0x00, 0x00,
|
|
50
|
+
0x00, 0x00, 0x00, 0x00,
|
|
51
|
+
0x00, 0x00, 0x00, 0x00,
|
|
52
|
+
0x00, 0x00, 0x00, 0x00 };
|
|
53
|
+
unsigned char env_decay[NUM_FM_OPS] = { 0x00, 0x00, 0x00, 0x00,
|
|
54
|
+
0x00, 0x00, 0x00, 0x00,
|
|
55
|
+
0x00, 0x00, 0x00, 0x00,
|
|
56
|
+
0x00, 0x00, 0x00, 0x00 };
|
|
57
|
+
unsigned char env_sustain[NUM_FM_OPS] = { 0x00, 0x00, 0x00, 0x00,
|
|
58
|
+
0x00, 0x00, 0x00, 0x00,
|
|
59
|
+
0x00, 0x00, 0x00, 0x00,
|
|
60
|
+
0x00, 0x00, 0x00, 0x00 };
|
|
61
|
+
|
|
62
|
+
unsigned char op_transpose[NUM_FM_OPS] = { 0, 0, 0, 0,
|
|
63
|
+
28, 12, 0, 19,
|
|
64
|
+
36, 0, 0, 0,
|
|
65
|
+
0, 0, 0, 0 };
|
|
66
|
+
|
|
67
|
+
#define MUSIC_CFG_VELOCITY 1
|
|
68
|
+
#define MUSIC_CFG_PROGCHANGE 2
|
|
69
|
+
|
|
70
|
+
#define MUSIC_FLAG_POP_AT_END 1
|
|
71
|
+
|
|
72
|
+
const unsigned char* paused_cursor = 0;
|
|
73
|
+
unsigned char paused_bank = 0;
|
|
74
|
+
unsigned char paused_cfg = 0;
|
|
75
|
+
unsigned char paused_delay;
|
|
76
|
+
unsigned char music_mode = REPEAT_NONE;
|
|
77
|
+
|
|
78
|
+
unsigned char music_channel_mask;
|
|
79
|
+
unsigned char percussion_channel_mask;
|
|
80
|
+
unsigned char note_held_mask;
|
|
81
|
+
const unsigned char* sound_effect_ptr[NUM_FM_CHANNELS];
|
|
82
|
+
unsigned char sound_effect_bank[NUM_FM_CHANNELS];
|
|
83
|
+
unsigned char sound_effect_length[NUM_FM_CHANNELS];
|
|
84
|
+
unsigned char saved_feedback_value[NUM_FM_CHANNELS];
|
|
85
|
+
unsigned char sound_effect_priority[NUM_FM_CHANNELS];
|
|
86
|
+
|
|
87
|
+
void init_music() {
|
|
88
|
+
char i;
|
|
89
|
+
music_stack_idx = 0;
|
|
90
|
+
music_state.cursor = 0;
|
|
91
|
+
music_state.delay = 0;
|
|
92
|
+
music_channel_mask = 255;
|
|
93
|
+
note_held_mask = 0;
|
|
94
|
+
for(i = 0; i < NUM_FM_CHANNELS; ++i) {
|
|
95
|
+
sound_effect_length[i] = 0;
|
|
96
|
+
sound_effect_priority[i] = 0;
|
|
97
|
+
}
|
|
98
|
+
stop_music();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void load_instrument(char channel, const Instrument* instr) {
|
|
102
|
+
if(instr == ((Instrument*) 0xFFFF)) {
|
|
103
|
+
percussion_channel_mask |= channel_masks[channel];
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
percussion_channel_mask &= ~channel_masks[channel];
|
|
107
|
+
music_state.instruments[channel] = instr;
|
|
108
|
+
channel_note_offset[channel] = instr->transpose;
|
|
109
|
+
aram[FEEDBACK_AMT + channel] = (instr->feedback << 3) + 128;
|
|
110
|
+
channel = channel << 2;
|
|
111
|
+
env_initial[channel] = instr->env_initial[0];
|
|
112
|
+
env_decay[channel] = instr->env_decay[0];
|
|
113
|
+
env_sustain[channel] = instr->env_sustain[0];
|
|
114
|
+
op_transpose[channel] = instr->op_transpose[0];
|
|
115
|
+
++channel;
|
|
116
|
+
env_initial[channel] = instr->env_initial[1];
|
|
117
|
+
env_decay[channel] = instr->env_decay[1];
|
|
118
|
+
env_sustain[channel] = instr->env_sustain[1];
|
|
119
|
+
op_transpose[channel] = instr->op_transpose[1];
|
|
120
|
+
++channel;
|
|
121
|
+
env_initial[channel] = instr->env_initial[2];
|
|
122
|
+
env_decay[channel] = instr->env_decay[2];
|
|
123
|
+
env_sustain[channel] = instr->env_sustain[2];
|
|
124
|
+
op_transpose[channel] = instr->op_transpose[2];
|
|
125
|
+
++channel;
|
|
126
|
+
env_initial[channel] = instr->env_initial[3];
|
|
127
|
+
env_decay[channel] = instr->env_decay[3];
|
|
128
|
+
env_sustain[channel] = instr->env_sustain[3];
|
|
129
|
+
op_transpose[channel] = instr->op_transpose[3];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
char n_mul;
|
|
133
|
+
void set_note(char ch, char n) {
|
|
134
|
+
n_mul = op_transpose[ch] + n;
|
|
135
|
+
n_mul += n_mul;
|
|
136
|
+
set_audio_param(PITCH_MSB + ch, pitch_table[n_mul]);
|
|
137
|
+
set_audio_param(PITCH_LSB + ch, pitch_table[n_mul + 1]);
|
|
138
|
+
++ch;
|
|
139
|
+
n_mul = op_transpose[ch] + n;
|
|
140
|
+
n_mul += n_mul;
|
|
141
|
+
set_audio_param(PITCH_MSB + ch, pitch_table[n_mul]);
|
|
142
|
+
set_audio_param(PITCH_LSB + ch, pitch_table[n_mul + 1]);
|
|
143
|
+
++ch;
|
|
144
|
+
n_mul = op_transpose[ch] + n;
|
|
145
|
+
n_mul += n_mul;
|
|
146
|
+
set_audio_param(PITCH_MSB + ch, pitch_table[n_mul]);
|
|
147
|
+
set_audio_param(PITCH_LSB + ch, pitch_table[n_mul + 1]);
|
|
148
|
+
++ch;
|
|
149
|
+
n_mul = op_transpose[ch] + n;
|
|
150
|
+
n_mul += n_mul;
|
|
151
|
+
set_audio_param(PITCH_MSB + ch, pitch_table[n_mul]);
|
|
152
|
+
set_audio_param(PITCH_LSB + ch, pitch_table[n_mul + 1]);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
void play_song(const unsigned char* song, char bank_num, char loop) {
|
|
156
|
+
char n;
|
|
157
|
+
push_song_stack();
|
|
158
|
+
music_state.bank = bank_num;
|
|
159
|
+
push_rom_bank();
|
|
160
|
+
change_rom_bank(music_state.bank);
|
|
161
|
+
music_state.cursor = song;
|
|
162
|
+
|
|
163
|
+
for(n = 0; n < NUM_FM_OPS; ++n) {
|
|
164
|
+
audio_amplitudes[n] = 0;
|
|
165
|
+
set_audio_param(AMPLITUDE+n, 128);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
switch(loop) {
|
|
169
|
+
case REPEAT_NONE:
|
|
170
|
+
music_state.repeat_ptr = 0;
|
|
171
|
+
music_mode = REPEAT_NONE;
|
|
172
|
+
music_state.flags = 0;
|
|
173
|
+
break;
|
|
174
|
+
case REPEAT_LOOP:
|
|
175
|
+
music_state.repeat_ptr = music_state.cursor;
|
|
176
|
+
music_mode = REPEAT_LOOP;
|
|
177
|
+
music_state.flags = 0;
|
|
178
|
+
break;
|
|
179
|
+
case REPEAT_RESUME:
|
|
180
|
+
music_state.flags = MUSIC_FLAG_POP_AT_END;
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if(music_state.cursor) {
|
|
185
|
+
percussion_channel_mask = 0;
|
|
186
|
+
music_state.cfg = *(music_state.cursor++);
|
|
187
|
+
load_instrument(0, get_instrument_ptr(*(music_state.cursor++)));
|
|
188
|
+
load_instrument(1, get_instrument_ptr(*(music_state.cursor++)));
|
|
189
|
+
load_instrument(2, get_instrument_ptr(*(music_state.cursor++)));
|
|
190
|
+
load_instrument(3, get_instrument_ptr(*(music_state.cursor++)));
|
|
191
|
+
music_state.delay = *(music_state.cursor++);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
pop_rom_bank();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
void pause_music() {
|
|
198
|
+
push_song_stack();
|
|
199
|
+
music_state.cursor = 0;
|
|
200
|
+
note_held_mask = 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
void unpause_music() {
|
|
204
|
+
pop_song_stack();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
void tick_music() {
|
|
208
|
+
static unsigned char n, noteMask, ch;
|
|
209
|
+
register unsigned char a, op;
|
|
210
|
+
push_rom_bank();
|
|
211
|
+
for(n = 0; n < NUM_FM_CHANNELS; ++n) {
|
|
212
|
+
if(sound_effect_length[n]) {
|
|
213
|
+
--sound_effect_length[n];
|
|
214
|
+
if(sound_effect_length[n]) {
|
|
215
|
+
|
|
216
|
+
change_rom_bank(sound_effect_bank[n]);
|
|
217
|
+
|
|
218
|
+
op = n << 2;
|
|
219
|
+
set_audio_param(AMPLITUDE + op, (*(sound_effect_ptr[n]+0) << 3) + 128);
|
|
220
|
+
a = *(sound_effect_ptr[n]+4) << 1;
|
|
221
|
+
set_audio_param(PITCH_MSB + op, pitch_table[a]);
|
|
222
|
+
set_audio_param(PITCH_LSB + op, pitch_table[a+1]);
|
|
223
|
+
|
|
224
|
+
++op;
|
|
225
|
+
set_audio_param(AMPLITUDE + op, (*(sound_effect_ptr[n]+1) << 3) + 128);
|
|
226
|
+
a = *(sound_effect_ptr[n]+5) << 1;
|
|
227
|
+
set_audio_param(PITCH_MSB + op, pitch_table[a]);
|
|
228
|
+
set_audio_param(PITCH_LSB + op, pitch_table[a+1]);
|
|
229
|
+
|
|
230
|
+
++op;
|
|
231
|
+
set_audio_param(AMPLITUDE + op, (*(sound_effect_ptr[n]+2) << 3) + 128);
|
|
232
|
+
a = *(sound_effect_ptr[n]+6) << 1;
|
|
233
|
+
set_audio_param(PITCH_MSB + op, pitch_table[a]);
|
|
234
|
+
set_audio_param(PITCH_LSB + op, pitch_table[a+1]);
|
|
235
|
+
|
|
236
|
+
++op;
|
|
237
|
+
set_audio_param(AMPLITUDE + op, (*(sound_effect_ptr[n]+3) << 3) + 128);
|
|
238
|
+
a = *(sound_effect_ptr[n]+7) << 1;
|
|
239
|
+
set_audio_param(PITCH_MSB + op, pitch_table[a]);
|
|
240
|
+
set_audio_param(PITCH_LSB + op, pitch_table[a+1]);
|
|
241
|
+
|
|
242
|
+
sound_effect_ptr[n] += 8;
|
|
243
|
+
|
|
244
|
+
} else {
|
|
245
|
+
op = n << 2;
|
|
246
|
+
set_audio_param(AMPLITUDE+(op+3), 128);
|
|
247
|
+
aram[FEEDBACK_AMT + n] = saved_feedback_value[n];
|
|
248
|
+
music_channel_mask |= channel_masks[n];
|
|
249
|
+
sound_effect_priority[n] = 0;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
change_rom_bank(music_state.bank);
|
|
255
|
+
op = 0;
|
|
256
|
+
for(ch = 1; ch < 16; ch = ch << 1) {
|
|
257
|
+
if(ch & ~(music_channel_mask & note_held_mask)) {
|
|
258
|
+
op+=4;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
for(a = 0; a < 4; ++a) {
|
|
262
|
+
if(((env_sustain[op] - audio_amplitudes[op]) ^ (env_decay[op])) & 0x80) {
|
|
263
|
+
audio_amplitudes[op] -= env_decay[op];
|
|
264
|
+
} else {
|
|
265
|
+
audio_amplitudes[op] = env_sustain[op];
|
|
266
|
+
}
|
|
267
|
+
set_audio_param(AMPLITUDE+op, (audio_amplitudes[op] >> 1) + 128);
|
|
268
|
+
++op;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if(music_state.cursor) {
|
|
273
|
+
loadAudioEvent:
|
|
274
|
+
if(music_state.delay > 0) {
|
|
275
|
+
music_state.delay--;
|
|
276
|
+
} else {
|
|
277
|
+
noteMask = *(music_state.cursor++);
|
|
278
|
+
for(ch = 0; ch < NUM_FM_CHANNELS; ++ch) {
|
|
279
|
+
if(channel_masks[ch] & noteMask) {
|
|
280
|
+
n = *(music_state.cursor++);
|
|
281
|
+
if(music_state.cfg & MUSIC_CFG_VELOCITY)
|
|
282
|
+
a = *(music_state.cursor++);
|
|
283
|
+
if(channel_masks[ch] & percussion_channel_mask) {
|
|
284
|
+
if(n > 0) play_sound_effect(n - 1, ch);
|
|
285
|
+
} else if(channel_masks[ch] & music_channel_mask) {
|
|
286
|
+
op = ch << 2;
|
|
287
|
+
if(n > 0) {
|
|
288
|
+
|
|
289
|
+
set_note(op, n + channel_note_offset[ch]);
|
|
290
|
+
audio_amplitudes[op] = env_initial[op];
|
|
291
|
+
set_audio_param(AMPLITUDE+op, (audio_amplitudes[op] >> 1) + 128);
|
|
292
|
+
++op;
|
|
293
|
+
audio_amplitudes[op] = env_initial[op];
|
|
294
|
+
set_audio_param(AMPLITUDE+op, (audio_amplitudes[op] >> 1) + 128);
|
|
295
|
+
++op;
|
|
296
|
+
audio_amplitudes[op] = env_initial[op];
|
|
297
|
+
set_audio_param(AMPLITUDE+op, (audio_amplitudes[op] >> 1) + 128);
|
|
298
|
+
++op;
|
|
299
|
+
if(music_state.cfg & MUSIC_CFG_VELOCITY)
|
|
300
|
+
audio_amplitudes[op] = a;
|
|
301
|
+
else
|
|
302
|
+
audio_amplitudes[op] = env_initial[op];
|
|
303
|
+
set_audio_param(AMPLITUDE+op, (audio_amplitudes[op] >> 1) + 128);
|
|
304
|
+
} else {
|
|
305
|
+
audio_amplitudes[op+3] = 0;
|
|
306
|
+
set_audio_param(AMPLITUDE+op+3, 128);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if(n) {
|
|
310
|
+
note_held_mask |= channel_masks[ch];
|
|
311
|
+
} else {
|
|
312
|
+
note_held_mask &= ~channel_masks[ch];
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
music_state.delay = *(music_state.cursor++);
|
|
317
|
+
if(music_state.delay == 0) {
|
|
318
|
+
if(music_state.flags & MUSIC_FLAG_POP_AT_END) {
|
|
319
|
+
pop_song_stack();
|
|
320
|
+
} else {
|
|
321
|
+
music_state.cursor = music_state.repeat_ptr;
|
|
322
|
+
if(music_state.cursor) {
|
|
323
|
+
music_state.cursor+=5; //skip cfg and instruments
|
|
324
|
+
music_state.delay = *(music_state.cursor++);
|
|
325
|
+
goto loadAudioEvent;
|
|
326
|
+
} else {
|
|
327
|
+
silence_all_channels();
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
--music_state.delay;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
flush_audio_params();
|
|
337
|
+
pop_rom_bank();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
void silence_all_channels() {
|
|
341
|
+
char n;
|
|
342
|
+
for(n = 0; n < NUM_FM_OPS; ++n) {
|
|
343
|
+
audio_amplitudes[n] = 0;
|
|
344
|
+
set_audio_param(AMPLITUDE+n, 128);
|
|
345
|
+
}
|
|
346
|
+
note_held_mask = 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
void stop_music() {
|
|
350
|
+
music_state.cursor = 0;
|
|
351
|
+
silence_all_channels();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
void play_sound_effect(char sfx_id, char channel) {
|
|
355
|
+
static char priority;
|
|
356
|
+
priority = channel & 0xF0;
|
|
357
|
+
channel &= 0x03;
|
|
358
|
+
if(priority < sound_effect_priority[channel]) return;
|
|
359
|
+
sound_effect_priority[channel] = priority;
|
|
360
|
+
push_rom_bank();
|
|
361
|
+
change_rom_bank(BANK_LOADERS);
|
|
362
|
+
sound_effect_bank[channel] = ASSET__sfx_bank_table[sfx_id];
|
|
363
|
+
sound_effect_ptr[channel] = ASSET__sfx_ptr_table[sfx_id];
|
|
364
|
+
change_rom_bank(sound_effect_bank[channel]);
|
|
365
|
+
sound_effect_length[channel] = *(sound_effect_ptr[channel]++) + 1;
|
|
366
|
+
saved_feedback_value[channel] = aram[FEEDBACK_AMT + channel];
|
|
367
|
+
aram[FEEDBACK_AMT + channel] = *(sound_effect_ptr[channel]++);
|
|
368
|
+
music_channel_mask &= ~(channel_masks[channel]);
|
|
369
|
+
pop_rom_bank();
|
|
370
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#ifndef MUSIC_H
|
|
2
|
+
#define MUSIC_H
|
|
3
|
+
|
|
4
|
+
#include "audio_coprocessor.h"
|
|
5
|
+
#include "instruments.h"
|
|
6
|
+
|
|
7
|
+
#define REPEAT_NONE 0
|
|
8
|
+
#define REPEAT_LOOP 1
|
|
9
|
+
#define REPEAT_RESUME 2
|
|
10
|
+
|
|
11
|
+
#define SFX_PRIORITY(x) (x<<4)
|
|
12
|
+
|
|
13
|
+
void init_music();
|
|
14
|
+
|
|
15
|
+
void play_song(const unsigned char* song, char bank_num, char loop);
|
|
16
|
+
|
|
17
|
+
void tick_music();
|
|
18
|
+
|
|
19
|
+
void silence_all_channels();
|
|
20
|
+
|
|
21
|
+
void stop_music();
|
|
22
|
+
|
|
23
|
+
void pause_music();
|
|
24
|
+
|
|
25
|
+
void unpause_music();
|
|
26
|
+
|
|
27
|
+
void set_note(char ch, char n);
|
|
28
|
+
|
|
29
|
+
extern unsigned char audio_amplitudes[NUM_FM_OPS];
|
|
30
|
+
|
|
31
|
+
void load_instrument(char channel, const Instrument* instr);
|
|
32
|
+
|
|
33
|
+
void play_sound_effect(char sfx_id, char channel);
|
|
34
|
+
|
|
35
|
+
#endif
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#ifndef NOTE_NUMBERS_H
|
|
2
|
+
#define NOTE_NUMBERS_H
|
|
3
|
+
|
|
4
|
+
#define RST 0
|
|
5
|
+
#define NUP 128
|
|
6
|
+
|
|
7
|
+
#define Cn1 24
|
|
8
|
+
#define Cs1 25
|
|
9
|
+
#define Df1 25
|
|
10
|
+
#define Dn1 26
|
|
11
|
+
#define Ds1 27
|
|
12
|
+
#define Ef1 27
|
|
13
|
+
#define En1 28
|
|
14
|
+
#define Fn1 29
|
|
15
|
+
#define Fs1 30
|
|
16
|
+
#define Gf1 30
|
|
17
|
+
#define Gn1 31
|
|
18
|
+
#define Gs1 32
|
|
19
|
+
#define Af1 32
|
|
20
|
+
#define An1 33
|
|
21
|
+
#define As1 34
|
|
22
|
+
#define Bf1 34
|
|
23
|
+
#define Bn1 35
|
|
24
|
+
|
|
25
|
+
#define Cn2 36
|
|
26
|
+
#define Cs2 37
|
|
27
|
+
#define Df2 37
|
|
28
|
+
#define Dn2 38
|
|
29
|
+
#define Ds2 39
|
|
30
|
+
#define Ef2 39
|
|
31
|
+
#define En2 40
|
|
32
|
+
#define Fn2 41
|
|
33
|
+
#define Fs2 42
|
|
34
|
+
#define Gf2 42
|
|
35
|
+
#define Gn2 43
|
|
36
|
+
#define Gs2 44
|
|
37
|
+
#define Af2 44
|
|
38
|
+
#define An2 45
|
|
39
|
+
#define As2 46
|
|
40
|
+
#define Bf2 46
|
|
41
|
+
#define Bn2 47
|
|
42
|
+
|
|
43
|
+
#define Cn3 48
|
|
44
|
+
#define Cs3 49
|
|
45
|
+
#define Df3 49
|
|
46
|
+
#define Dn3 50
|
|
47
|
+
#define Ds3 51
|
|
48
|
+
#define Ef3 51
|
|
49
|
+
#define En3 52
|
|
50
|
+
#define Fn3 53
|
|
51
|
+
#define Fs3 54
|
|
52
|
+
#define Gf3 54
|
|
53
|
+
#define Gn3 55
|
|
54
|
+
#define Gs3 56
|
|
55
|
+
#define Af3 56
|
|
56
|
+
#define An3 57
|
|
57
|
+
#define As3 58
|
|
58
|
+
#define Bf3 58
|
|
59
|
+
#define Bn3 59
|
|
60
|
+
|
|
61
|
+
#define Cn4 60
|
|
62
|
+
#define Cs4 61
|
|
63
|
+
#define Df4 61
|
|
64
|
+
#define Dn4 62
|
|
65
|
+
#define Ds4 63
|
|
66
|
+
#define Ef4 63
|
|
67
|
+
#define En4 64
|
|
68
|
+
#define Fn4 65
|
|
69
|
+
#define Fs4 66
|
|
70
|
+
#define Gf4 66
|
|
71
|
+
#define Gn4 67
|
|
72
|
+
#define Gs4 68
|
|
73
|
+
#define Af4 68
|
|
74
|
+
#define An4 69
|
|
75
|
+
#define As4 70
|
|
76
|
+
#define Bf4 70
|
|
77
|
+
#define Bn4 71
|
|
78
|
+
|
|
79
|
+
#define Cn5 72
|
|
80
|
+
#define Cs5 73
|
|
81
|
+
#define Df5 73
|
|
82
|
+
#define Dn5 74
|
|
83
|
+
#define Ds5 75
|
|
84
|
+
#define Ef5 75
|
|
85
|
+
#define En5 76
|
|
86
|
+
#define Fn5 77
|
|
87
|
+
#define Fs5 78
|
|
88
|
+
#define Gf5 78
|
|
89
|
+
#define Gn5 79
|
|
90
|
+
#define Gs5 80
|
|
91
|
+
#define Af5 80
|
|
92
|
+
#define An5 81
|
|
93
|
+
#define As5 82
|
|
94
|
+
#define Bf5 82
|
|
95
|
+
#define Bn5 83
|
|
96
|
+
|
|
97
|
+
#define Cn6 84
|
|
98
|
+
#define Cs6 85
|
|
99
|
+
#define Df6 85
|
|
100
|
+
#define Dn6 86
|
|
101
|
+
#define Ds6 87
|
|
102
|
+
#define Ef6 87
|
|
103
|
+
#define En6 88
|
|
104
|
+
#define Fn6 89
|
|
105
|
+
#define Fs6 90
|
|
106
|
+
#define Gf6 90
|
|
107
|
+
#define Gn6 91
|
|
108
|
+
#define Gs6 92
|
|
109
|
+
#define Af6 92
|
|
110
|
+
#define An6 93
|
|
111
|
+
#define As6 94
|
|
112
|
+
#define Bf6 94
|
|
113
|
+
#define Bn6 95
|
|
114
|
+
|
|
115
|
+
#define Cn7 96
|
|
116
|
+
#define Cs7 97
|
|
117
|
+
#define Df7 97
|
|
118
|
+
#define Dn7 98
|
|
119
|
+
#define Ds7 99
|
|
120
|
+
#define Ef7 99
|
|
121
|
+
#define En7 100
|
|
122
|
+
#define Fn7 101
|
|
123
|
+
#define Fs7 102
|
|
124
|
+
#define Gf7 102
|
|
125
|
+
#define Gn7 103
|
|
126
|
+
#define Gs7 104
|
|
127
|
+
#define Af7 104
|
|
128
|
+
#define An7 105
|
|
129
|
+
#define As7 106
|
|
130
|
+
#define Bf7 106
|
|
131
|
+
#define Bn7 107
|
|
132
|
+
#endif
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#include "gametank.h"
|
|
2
|
+
|
|
3
|
+
//must be power of 2
|
|
4
|
+
#define BANK_STACK_SIZE 8
|
|
5
|
+
//must be BANK_STACK_SIZE-1
|
|
6
|
+
#define BANK_WRAP_MASK 7
|
|
7
|
+
|
|
8
|
+
unsigned char romBankMirror;
|
|
9
|
+
unsigned char romBankStack[BANK_STACK_SIZE];
|
|
10
|
+
unsigned char romBankStackIdx;
|
|
11
|
+
|
|
12
|
+
void bank_shift_out(unsigned char banknum);
|
|
13
|
+
|
|
14
|
+
void change_rom_bank(unsigned char banknum) {
|
|
15
|
+
if(banknum != romBankMirror)
|
|
16
|
+
bank_shift_out(banknum);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void push_rom_bank() {
|
|
20
|
+
romBankStackIdx = (romBankStackIdx + 1) & BANK_WRAP_MASK;
|
|
21
|
+
romBankStack[romBankStackIdx] = romBankMirror;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void pop_rom_bank() {
|
|
25
|
+
change_rom_bank(romBankStack[romBankStackIdx]);
|
|
26
|
+
if(romBankStackIdx == 0)
|
|
27
|
+
romBankStackIdx = BANK_STACK_SIZE;
|
|
28
|
+
--romBankStackIdx;
|
|
29
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
.export _bank_shift_out
|
|
2
|
+
.import _romBankMirror
|
|
3
|
+
|
|
4
|
+
; ---------------------------------------------------------------
|
|
5
|
+
; void __near__ bank_shift_out ()
|
|
6
|
+
; ---------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
OutBits = $2801
|
|
9
|
+
|
|
10
|
+
.segment "CODE"
|
|
11
|
+
|
|
12
|
+
.proc _bank_shift_out: near
|
|
13
|
+
sta _romBankMirror;
|
|
14
|
+
stz OutBits
|
|
15
|
+
clc
|
|
16
|
+
rol
|
|
17
|
+
rol
|
|
18
|
+
rol
|
|
19
|
+
tay
|
|
20
|
+
|
|
21
|
+
.repeat 7
|
|
22
|
+
and #2
|
|
23
|
+
sta OutBits
|
|
24
|
+
ora #1
|
|
25
|
+
sta OutBits
|
|
26
|
+
tya
|
|
27
|
+
rol
|
|
28
|
+
tay
|
|
29
|
+
.endrepeat
|
|
30
|
+
|
|
31
|
+
and #2
|
|
32
|
+
sta OutBits
|
|
33
|
+
ora #1
|
|
34
|
+
sta OutBits
|
|
35
|
+
ora #4
|
|
36
|
+
sta OutBits
|
|
37
|
+
stz OutBits
|
|
38
|
+
|
|
39
|
+
rts
|
|
40
|
+
|
|
41
|
+
.endproc
|