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
|
@@ -977,16 +977,33 @@ export async function readProjectDir(projPath, platform, opts = {}) {
|
|
|
977
977
|
const subAssets = await walkSubdirAssets(projPath);
|
|
978
978
|
|
|
979
979
|
// Entry override: an existing project whose top file isn't main.* (e.g.
|
|
980
|
-
// smw.asm)
|
|
981
|
-
//
|
|
982
|
-
|
|
980
|
+
// smw.asm) OR is nested (e.g. src/main.c — common for decomps/SDK projects).
|
|
981
|
+
// Accept a project-relative path or a bare name; it becomes the single entry
|
|
982
|
+
// source. Resolve against BOTH the top-level files AND the recursively staged
|
|
983
|
+
// subdir set, with POSIX slashes (`path.normalize` may emit `\` on Windows).
|
|
984
|
+
const entryName = opts.entry
|
|
985
|
+
? path.normalize(opts.entry).replace(/\\/g, "/").replace(/^[./]+/, "")
|
|
986
|
+
: null;
|
|
987
|
+
// The resolved {rel, abs} for the entry when it's nested in a subdirectory.
|
|
988
|
+
let entrySubAsset = null;
|
|
983
989
|
if (entryName) {
|
|
984
|
-
const
|
|
985
|
-
|
|
986
|
-
if
|
|
990
|
+
const topMatch = files.some((f) => f.name === entryName);
|
|
991
|
+
entrySubAsset = subAssets.find((a) => a.rel === entryName) || null;
|
|
992
|
+
// Bare-filename fallback: `entry:'main.c'` matches `src/main.c` if unique.
|
|
993
|
+
if (!topMatch && !entrySubAsset && !entryName.includes("/")) {
|
|
994
|
+
const byBase = subAssets.filter((a) => a.rel.split("/").pop() === entryName);
|
|
995
|
+
if (byBase.length === 1) entrySubAsset = byBase[0];
|
|
996
|
+
}
|
|
997
|
+
if (!topMatch && !entrySubAsset) {
|
|
998
|
+
const nearby = subAssets
|
|
999
|
+
.filter((a) => a.rel.split("/").pop() === entryName.split("/").pop())
|
|
1000
|
+
.map((a) => a.rel).slice(0, 8);
|
|
987
1001
|
throw new Error(
|
|
988
|
-
`entry '${entryName}' not found in ${projPath}.
|
|
989
|
-
|
|
1002
|
+
`entry '${entryName}' not found in ${projPath}. ` +
|
|
1003
|
+
(nearby.length
|
|
1004
|
+
? `Did you mean: ${nearby.join(", ")}? (entry is project-relative — e.g. 'src/main.c'.)`
|
|
1005
|
+
: `Top-level: ${files.map((f) => f.name).join(", ") || "(none)"}. ` +
|
|
1006
|
+
`entry is project-relative — pass the path under the repo root (e.g. 'src/main.c').`)
|
|
990
1007
|
);
|
|
991
1008
|
}
|
|
992
1009
|
}
|
|
@@ -1006,7 +1023,7 @@ export async function readProjectDir(projPath, platform, opts = {}) {
|
|
|
1006
1023
|
// the dir build matches the hand-written build({output:'run'}) call.
|
|
1007
1024
|
const recipe = projectBuildRecipe(platform, files.map((f) => f.name));
|
|
1008
1025
|
|
|
1009
|
-
// With a custom entry, the entry is the ONE source; every OTHER top-level
|
|
1026
|
+
// With a custom ASM entry, the entry is the ONE source; every OTHER top-level
|
|
1010
1027
|
// .asm/.s/.c routes as an include (asar/wla resolve `.include`/`#include`
|
|
1011
1028
|
// from the includes mount), matching the single-source asm model.
|
|
1012
1029
|
if (entryName && /\.(asm|s)$/i.test(entryName)) {
|
|
@@ -1040,7 +1057,7 @@ export async function readProjectDir(projPath, platform, opts = {}) {
|
|
|
1040
1057
|
// the mount. Text-ish includes (.asm/.s/.h/.inc) found in subdirs go to includes
|
|
1041
1058
|
// (so `incsrc "lib/foo.asm"` works); everything else is a binary asset.
|
|
1042
1059
|
for (const a of subAssets) {
|
|
1043
|
-
if (recipe.skip.has(a.rel) || a.rel ===
|
|
1060
|
+
if (recipe.skip.has(a.rel) || a.rel === entrySubAsset?.rel) continue;
|
|
1044
1061
|
if (/\.(h|inc|asm|s)$/i.test(a.rel)) {
|
|
1045
1062
|
includes[a.rel] = (await readFile(a.abs)).toString("utf-8");
|
|
1046
1063
|
} else {
|
|
@@ -1048,6 +1065,14 @@ export async function readProjectDir(projPath, platform, opts = {}) {
|
|
|
1048
1065
|
}
|
|
1049
1066
|
}
|
|
1050
1067
|
|
|
1068
|
+
// A NESTED entry (e.g. src/main.c) is read here as the entry SOURCE — the
|
|
1069
|
+
// top-level loop above only sees root files, so a subdir entry would otherwise
|
|
1070
|
+
// never compile. Keyed by its relative path so #include/.include resolution
|
|
1071
|
+
// from the same subdir works.
|
|
1072
|
+
if (entrySubAsset) {
|
|
1073
|
+
sources[entrySubAsset.rel] = (await readFile(entrySubAsset.abs)).toString("utf-8");
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1051
1076
|
// SMS/GG with no crt0 file in the dir → fall back to the bundled crt0,
|
|
1052
1077
|
// exactly like the output:'rom'/'run' handlers do. Without this the link
|
|
1053
1078
|
// silently uses SDCC's stock z80 crt0, which never calls main() (black
|
|
Binary file
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#include <zlib.h>
|
|
2
|
+
#include "audio_coprocessor.h"
|
|
3
|
+
#include "gametank.h"
|
|
4
|
+
#include "banking.h"
|
|
5
|
+
#include "bank_nums.h"
|
|
6
|
+
|
|
7
|
+
char pitch_table[216] = {
|
|
8
|
+
0x00, 0x4D, 0x00, 0x51, 0x00, 0x56, 0x00, 0x5B, 0x00, 0x61, 0x00, 0x66, 0x00, 0x6C, 0x00, 0x73, 0x00, 0x7A, 0x00, 0x81, 0x00, 0x89, 0x00, 0x91,
|
|
9
|
+
0x00, 0x99, 0x00, 0xA2, 0x00, 0xAC, 0x00, 0xB6, 0x00, 0xC1, 0x00, 0xCD, 0x00, 0xD9, 0x00, 0xE6, 0x00, 0xF3, 0x01, 0x02, 0x01, 0x11, 0x01, 0x21,
|
|
10
|
+
0x01, 0x33, 0x01, 0x45, 0x01, 0x58, 0x01, 0x6D, 0x01, 0x82, 0x01, 0x99, 0x01, 0xB2, 0x01, 0xCB, 0x01, 0xE7, 0x02, 0x04, 0x02, 0x22, 0x02, 0x43,
|
|
11
|
+
0x02, 0x65, 0x02, 0x8A, 0x02, 0xB0, 0x02, 0xD9, 0x03, 0x04, 0x03, 0x32, 0x03, 0x63, 0x03, 0x97, 0x03, 0xCD, 0x04, 0x07, 0x04, 0x44, 0x04, 0x85,
|
|
12
|
+
0x04, 0xCA, 0x05, 0x13, 0x05, 0x60, 0x05, 0xB2, 0x06, 0x09, 0x06, 0x65, 0x06, 0xC6, 0x07, 0x2D, 0x07, 0x9A, 0x08, 0x0E, 0x08, 0x89, 0x09, 0x0B,
|
|
13
|
+
0x09, 0x94, 0x0A, 0x26, 0x0A, 0xC1, 0x0B, 0x64, 0x0C, 0x12, 0x0C, 0xCA, 0x0D, 0x8C, 0x0E, 0x5B, 0x0F, 0x35, 0x10, 0x1D, 0x11, 0x12, 0x12, 0x16,
|
|
14
|
+
0x13, 0x29, 0x14, 0x4D, 0x15, 0x82, 0x16, 0xC9, 0x18, 0x24, 0x19, 0x93, 0x1B, 0x19, 0x1C, 0xB5, 0x1E, 0x6A, 0x20, 0x39, 0x22, 0x24, 0x24, 0x2B,
|
|
15
|
+
0x26, 0x52, 0x28, 0x99, 0x2B, 0x03, 0x2D, 0x92, 0x30, 0x48, 0x33, 0x27, 0x36, 0x31, 0x39, 0x6A, 0x3C, 0xD4, 0x40, 0x72, 0x44, 0x47, 0x48, 0x57,
|
|
16
|
+
0x4C, 0xA4, 0x51, 0x32, 0x56, 0x06, 0x5B, 0x24, 0x60, 0x8F, 0x66, 0x4D, 0x6C, 0x62, 0x72, 0xD4, 0x79, 0xA8, 0x80, 0xE4, 0x88, 0x8E, 0x90, 0xAD};
|
|
17
|
+
|
|
18
|
+
extern const unsigned char AudioFWPkg;
|
|
19
|
+
|
|
20
|
+
char audio_params_index = 0;
|
|
21
|
+
char *wavetable_page;
|
|
22
|
+
char sine_offset = 0;
|
|
23
|
+
|
|
24
|
+
void wait();
|
|
25
|
+
|
|
26
|
+
void init_audio_coprocessor()
|
|
27
|
+
{
|
|
28
|
+
*audio_rate = 0x7F;
|
|
29
|
+
|
|
30
|
+
push_rom_bank();
|
|
31
|
+
change_rom_bank(BANK_COMMON);
|
|
32
|
+
{ unsigned int _i; const unsigned char *_s = &AudioFWPkg; for(_i=0;_i<4096;_i++) aram[_i]=_s[_i]; } /* raw copy (uncompressed FW, no zopfli on the bare path) */
|
|
33
|
+
|
|
34
|
+
audio_params_index = 0;
|
|
35
|
+
AUDIO_PARAM_INPUT_BUFFER[0] = 0;
|
|
36
|
+
*audio_reset = 0;
|
|
37
|
+
*audio_rate = 255;
|
|
38
|
+
while(*WAVE_TABLE_LOCATION == 0) {
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
wavetable_page = ((char*) 0x3000) + *WAVE_TABLE_LOCATION;
|
|
42
|
+
sine_offset = *((char*)0x3003);
|
|
43
|
+
pop_rom_bank();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void push_audio_param(char param, char value) {
|
|
47
|
+
AUDIO_PARAM_INPUT_BUFFER[audio_params_index++] = param;
|
|
48
|
+
AUDIO_PARAM_INPUT_BUFFER[audio_params_index++] = value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
void flush_audio_params() {
|
|
52
|
+
AUDIO_PARAM_INPUT_BUFFER[audio_params_index] = 0;
|
|
53
|
+
*audio_nmi = 1;
|
|
54
|
+
audio_params_index = 0;
|
|
55
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#ifndef AUDIO_COPROCESSOR_H
|
|
2
|
+
|
|
3
|
+
#define AUDIO_COPROCESSOR_H
|
|
4
|
+
|
|
5
|
+
#define FEEDBACK_AMT 0x04
|
|
6
|
+
|
|
7
|
+
#define PITCH_MSB 0x10
|
|
8
|
+
|
|
9
|
+
#define PITCH_LSB 0x20
|
|
10
|
+
|
|
11
|
+
#define AMPLITUDE 0x30
|
|
12
|
+
|
|
13
|
+
#define AUDIO_PARAM_INPUT_BUFFER ((volatile char *) 0x3070)
|
|
14
|
+
#define WAVE_TABLE_LOCATION ((volatile unsigned int *) 0x3002)
|
|
15
|
+
|
|
16
|
+
#define NUM_FM_CHANNELS 4
|
|
17
|
+
#define OPS_PER_CHANNEL 4
|
|
18
|
+
#define NUM_FM_OPS 16
|
|
19
|
+
|
|
20
|
+
extern char pitch_table[216];
|
|
21
|
+
|
|
22
|
+
void init_audio_coprocessor();
|
|
23
|
+
|
|
24
|
+
void push_audio_param(char param, char value);
|
|
25
|
+
|
|
26
|
+
#define set_audio_param(param,value) aram[param]=value
|
|
27
|
+
|
|
28
|
+
void flush_audio_params();
|
|
29
|
+
|
|
30
|
+
extern char* wavetable_page;
|
|
31
|
+
|
|
32
|
+
extern char sine_offset;
|
|
33
|
+
|
|
34
|
+
#endif
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
DAC = $8000
|
|
2
|
+
AccBuf = $00
|
|
3
|
+
WavePTR = $02
|
|
4
|
+
WavePTR_MSB = $03
|
|
5
|
+
FeedbackAmount = $04
|
|
6
|
+
;reserve $05
|
|
7
|
+
;reserve $06
|
|
8
|
+
;reserve $07
|
|
9
|
+
LastSample = $08
|
|
10
|
+
;reserve $09
|
|
11
|
+
;reserve $0A
|
|
12
|
+
;reserve $0B
|
|
13
|
+
FreqsH = $10
|
|
14
|
+
FreqsL = $20
|
|
15
|
+
BufferedAmplitudes = $30
|
|
16
|
+
WaveStatesH = $50
|
|
17
|
+
WaveStatesL = $60
|
|
18
|
+
Inputs = $70
|
|
19
|
+
.zeropage
|
|
20
|
+
;AccBuf
|
|
21
|
+
.byte 0, 0
|
|
22
|
+
;WavePTR
|
|
23
|
+
.byte 0, 0
|
|
24
|
+
;Feedback
|
|
25
|
+
.byte $80, $80, $80, $80
|
|
26
|
+
;UNUSED
|
|
27
|
+
.repeat 8
|
|
28
|
+
.byte 0
|
|
29
|
+
.endrep
|
|
30
|
+
;Frequencies
|
|
31
|
+
.repeat $20
|
|
32
|
+
.byte 0
|
|
33
|
+
.endrep
|
|
34
|
+
;Amplitudes
|
|
35
|
+
.repeat $10
|
|
36
|
+
.byte $80
|
|
37
|
+
.endrep
|
|
38
|
+
;Wave States
|
|
39
|
+
.repeat $80
|
|
40
|
+
.byte 0
|
|
41
|
+
.endrep
|
|
42
|
+
|
|
43
|
+
.code
|
|
44
|
+
RESET:
|
|
45
|
+
CLI
|
|
46
|
+
LDA #<Sine
|
|
47
|
+
STA WavePTR
|
|
48
|
+
LDA #>Sine
|
|
49
|
+
STA WavePTR+1
|
|
50
|
+
Forever:
|
|
51
|
+
WAI
|
|
52
|
+
JMP Forever
|
|
53
|
+
|
|
54
|
+
.macro tickWave op, out
|
|
55
|
+
CLC
|
|
56
|
+
LDA WaveStatesL+op
|
|
57
|
+
ADC FreqsL+op
|
|
58
|
+
STA WaveStatesL+op
|
|
59
|
+
LDA out
|
|
60
|
+
ADC FreqsH+op
|
|
61
|
+
STA out
|
|
62
|
+
.endmacro
|
|
63
|
+
|
|
64
|
+
.macro doChannel ch
|
|
65
|
+
.local Op1
|
|
66
|
+
.local Op1State
|
|
67
|
+
.local Op1Param
|
|
68
|
+
.local Op2
|
|
69
|
+
.local Op2Param
|
|
70
|
+
.local Op3
|
|
71
|
+
.local Op3Param
|
|
72
|
+
.local Op4
|
|
73
|
+
.local Op4Param
|
|
74
|
+
.local SaveFeedback
|
|
75
|
+
.local SampleFeedback
|
|
76
|
+
.local LastSample
|
|
77
|
+
|
|
78
|
+
LDA BufferedAmplitudes+(ch*4)+0
|
|
79
|
+
STA Op1+1
|
|
80
|
+
LDA BufferedAmplitudes+(ch*4)+1
|
|
81
|
+
STA Op2+1
|
|
82
|
+
LDA BufferedAmplitudes+(ch*4)+2
|
|
83
|
+
STA Op3+1
|
|
84
|
+
LDA BufferedAmplitudes+(ch*4)+3
|
|
85
|
+
STA Op4+1
|
|
86
|
+
|
|
87
|
+
tickWave (ch*4)+1, Op2Param+1
|
|
88
|
+
tickWave (ch*4)+2, Op3Param+1
|
|
89
|
+
tickWave (ch*4)+3, Op4Param+1
|
|
90
|
+
|
|
91
|
+
tickWave (ch * 4), Op1State+1
|
|
92
|
+
Op1State:
|
|
93
|
+
LDA #0
|
|
94
|
+
LastSample:
|
|
95
|
+
ADC #0
|
|
96
|
+
|
|
97
|
+
TAY
|
|
98
|
+
CLC
|
|
99
|
+
SampleFeedback:
|
|
100
|
+
ADC FeedbackAmount+ch
|
|
101
|
+
TAX
|
|
102
|
+
CLC
|
|
103
|
+
LDA Sine, y
|
|
104
|
+
ADC Sine, x
|
|
105
|
+
|
|
106
|
+
SaveFeedback:
|
|
107
|
+
STA LastSample+1
|
|
108
|
+
TYA
|
|
109
|
+
|
|
110
|
+
CLC
|
|
111
|
+
Op1:
|
|
112
|
+
ADC #0
|
|
113
|
+
TAX
|
|
114
|
+
CLC
|
|
115
|
+
LDA Sine, y
|
|
116
|
+
ADC Sine, x
|
|
117
|
+
|
|
118
|
+
CLC
|
|
119
|
+
Op2Param:
|
|
120
|
+
ADC #0
|
|
121
|
+
TAY
|
|
122
|
+
CLC
|
|
123
|
+
Op2:
|
|
124
|
+
ADC #0
|
|
125
|
+
TAX
|
|
126
|
+
CLC
|
|
127
|
+
LDA Sine, y
|
|
128
|
+
ADC Sine, x
|
|
129
|
+
|
|
130
|
+
CLC
|
|
131
|
+
Op3Param:
|
|
132
|
+
ADC #0
|
|
133
|
+
TAY
|
|
134
|
+
CLC
|
|
135
|
+
Op3:
|
|
136
|
+
ADC #0
|
|
137
|
+
TAX
|
|
138
|
+
CLC
|
|
139
|
+
LDA Sine, y
|
|
140
|
+
ADC Sine, x
|
|
141
|
+
|
|
142
|
+
CLC
|
|
143
|
+
Op4Param:
|
|
144
|
+
ADC #0
|
|
145
|
+
TAY
|
|
146
|
+
CLC
|
|
147
|
+
Op4:
|
|
148
|
+
ADC #0
|
|
149
|
+
TAX
|
|
150
|
+
CLC
|
|
151
|
+
LDA Sine, y
|
|
152
|
+
ADC Sine, x
|
|
153
|
+
|
|
154
|
+
CMP #$80
|
|
155
|
+
ROR
|
|
156
|
+
CMP #$80
|
|
157
|
+
ROR
|
|
158
|
+
|
|
159
|
+
CLC
|
|
160
|
+
ADC AccBuf
|
|
161
|
+
STA AccBuf
|
|
162
|
+
.endmacro
|
|
163
|
+
|
|
164
|
+
.macro GetSine
|
|
165
|
+
.local ScaleConstant
|
|
166
|
+
; Returns sin(Acc + X) + sin(Acc - X)
|
|
167
|
+
TAY
|
|
168
|
+
STX ScaleConstant+1
|
|
169
|
+
CLC
|
|
170
|
+
ScaleConstant:
|
|
171
|
+
ADC #0
|
|
172
|
+
TAX
|
|
173
|
+
CLC
|
|
174
|
+
LDA Sine, y
|
|
175
|
+
ADC Sine, x
|
|
176
|
+
.endmacro
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
IRQ:
|
|
180
|
+
;Clear sum buffer
|
|
181
|
+
STZ AccBuf
|
|
182
|
+
|
|
183
|
+
doChannel 0
|
|
184
|
+
doChannel 1
|
|
185
|
+
doChannel 2
|
|
186
|
+
doChannel 3
|
|
187
|
+
|
|
188
|
+
LDA AccBuf
|
|
189
|
+
CLC
|
|
190
|
+
ADC #$80
|
|
191
|
+
STA DAC
|
|
192
|
+
|
|
193
|
+
RTI ;6
|
|
194
|
+
|
|
195
|
+
;Read inputs addr, val until addr=0
|
|
196
|
+
NMI_handler:
|
|
197
|
+
PHY
|
|
198
|
+
PHX
|
|
199
|
+
PHA
|
|
200
|
+
LDY #0
|
|
201
|
+
NMI_Loop:
|
|
202
|
+
LDX Inputs, y
|
|
203
|
+
BEQ NMI_Done
|
|
204
|
+
INY
|
|
205
|
+
LDA Inputs, y
|
|
206
|
+
STA $00, x
|
|
207
|
+
INY
|
|
208
|
+
JMP NMI_Loop
|
|
209
|
+
|
|
210
|
+
NMI_Done:
|
|
211
|
+
PLA
|
|
212
|
+
PLX
|
|
213
|
+
PLY
|
|
214
|
+
RTI
|
|
215
|
+
|
|
216
|
+
.segment "WAVES"
|
|
217
|
+
Sine:
|
|
218
|
+
.incbin "sine_256_-63_63.bin"
|
|
219
|
+
|
|
220
|
+
.segment "VECTORS"
|
|
221
|
+
.addr NMI_handler
|
|
222
|
+
.addr RESET
|
|
223
|
+
.addr IRQ
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
; romdev single-bank GameTank: the ACP firmware embedded UNCOMPRESSED (the SDK
|
|
2
|
+
; deflate-compresses it + inflatemem()s it; the bare path has no zopfli, so we
|
|
3
|
+
; assemble audio_fw.asm to a raw 4 KB ACP image and memcpy it in). The build
|
|
4
|
+
; stages the assembled image next to this file as acp_image.bin.
|
|
5
|
+
.export _AudioFWPkg
|
|
6
|
+
.segment "COMMON"
|
|
7
|
+
_AudioFWPkg:
|
|
8
|
+
.incbin "acp_image.bin"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#include "instruments.h"
|
|
2
|
+
|
|
3
|
+
const Instrument piano = {
|
|
4
|
+
0x30, 0x40, 0x40, 0x5f,
|
|
5
|
+
0x04, 0x02, 0x10, 0x02,
|
|
6
|
+
0x04, 0x02, 0x10, 0x30,
|
|
7
|
+
0, 0, 0, 0,
|
|
8
|
+
0,
|
|
9
|
+
0
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const Instrument guitar = {
|
|
13
|
+
0x6f, 0x40, 0x68, 0x5f, //initial amplitudes
|
|
14
|
+
0x00, 0xFF, 0x02, 0x08, //decay rates
|
|
15
|
+
0x00, 0x00, 0x40, 0x08, //sustain values
|
|
16
|
+
12, 36, 0, 24, //per operator note offsets
|
|
17
|
+
8, //feedback amount
|
|
18
|
+
-12 //channel note offset
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const Instrument guitar2 = {
|
|
22
|
+
0x60, 0x40, 0x88, 0x4f,
|
|
23
|
+
0x00, 0xFF, 0x02, 0x01,
|
|
24
|
+
0x00, 0x00, 0x40, 0x30,
|
|
25
|
+
12, 36, 0, 24,
|
|
26
|
+
8,
|
|
27
|
+
-12
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const Instrument slapbass = {
|
|
31
|
+
0x58, 0x88, 0x58, 0x5f,
|
|
32
|
+
0x18, 0x08, 0x04, 0x02,
|
|
33
|
+
0x18, 0x08, 0x04, 0x02,
|
|
34
|
+
28, 12, 0, 12,
|
|
35
|
+
0,
|
|
36
|
+
-24
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const Instrument snare = {
|
|
40
|
+
0x88, 0x8f, 0x8f, 0x38,
|
|
41
|
+
0x18, 0x02, 0x04, 0x04,
|
|
42
|
+
0x18, 0x08, 0x08, 0x04,
|
|
43
|
+
36, 0, 0, 0,
|
|
44
|
+
8,
|
|
45
|
+
-8
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const Instrument sitar = {
|
|
49
|
+
0x60, 0x40, 0x01, 0x10,
|
|
50
|
+
0x00, 0xFF, 0xF8, 0xFF,
|
|
51
|
+
0x00, 0x60, 0x60, 0x30,
|
|
52
|
+
12, 36, 12, 24,
|
|
53
|
+
4,
|
|
54
|
+
-24
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const Instrument horn = {
|
|
58
|
+
0x00, 0x00, 0x01, 0x10,
|
|
59
|
+
0x00, 0x00, 0xFC, 0xFC,
|
|
60
|
+
0x00, 0x00, 0x30, 0x50,
|
|
61
|
+
12, 36, 12, 24,
|
|
62
|
+
0,
|
|
63
|
+
-12
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
Instrument* instrument_table[] = {
|
|
67
|
+
(Instrument*) 0xFFFF,
|
|
68
|
+
&piano,
|
|
69
|
+
&guitar,
|
|
70
|
+
&guitar2,
|
|
71
|
+
&slapbass,
|
|
72
|
+
&snare,
|
|
73
|
+
&sitar,
|
|
74
|
+
&horn
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
Instrument* get_instrument_ptr(char idx) {
|
|
78
|
+
return instrument_table[idx];
|
|
79
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#ifndef INSTRUMENTS_H
|
|
2
|
+
#define INSTRUMENTS_H
|
|
3
|
+
|
|
4
|
+
#include "audio_coprocessor.h"
|
|
5
|
+
|
|
6
|
+
typedef struct {
|
|
7
|
+
unsigned char env_initial[OPS_PER_CHANNEL];
|
|
8
|
+
unsigned char env_decay[OPS_PER_CHANNEL];
|
|
9
|
+
unsigned char env_sustain[OPS_PER_CHANNEL];
|
|
10
|
+
unsigned char op_transpose[OPS_PER_CHANNEL];
|
|
11
|
+
unsigned char feedback;
|
|
12
|
+
signed char transpose;
|
|
13
|
+
} Instrument;
|
|
14
|
+
|
|
15
|
+
#define INSTR_IDX_PIANO 1
|
|
16
|
+
#define INSTR_IDX_GUITAR 2
|
|
17
|
+
#define INSTR_IDX_DISTGUITAR 3
|
|
18
|
+
#define INSTR_IDX_SLAPBASS 4
|
|
19
|
+
#define INSTR_IDX_SNARE 5
|
|
20
|
+
#define INSTR_IDX_SITAR 6
|
|
21
|
+
#define INSTR_IDX_HORN 7
|
|
22
|
+
|
|
23
|
+
Instrument* get_instrument_ptr(char idx);
|
|
24
|
+
|
|
25
|
+
#endif
|