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.
Files changed (113) hide show
  1. package/AGENTS.md +19 -16
  2. package/CHANGELOG.md +196 -0
  3. package/README.md +5 -5
  4. package/examples/README.md +1 -0
  5. package/examples/gametank/templates/gt_draw.h +91 -0
  6. package/examples/gametank/templates/gt_hud.h +89 -0
  7. package/examples/gametank/templates/gt_palette.h +59 -0
  8. package/examples/gametank/templates/gt_sound.h +90 -0
  9. package/examples/gametank/templates/gt_sprites.h +53 -0
  10. package/examples/gametank/templates/platformer.c +318 -0
  11. package/examples/gametank/templates/puzzle.c +295 -0
  12. package/examples/gametank/templates/racing.c +139 -0
  13. package/examples/gametank/templates/shmup.c +277 -0
  14. package/examples/gametank/templates/sports.c +119 -0
  15. package/package.json +23 -22
  16. package/src/cores/capabilities.js +24 -0
  17. package/src/cores/registry.js +7 -1
  18. package/src/host/LibretroHost.js +90 -17
  19. package/src/host/callbacks.js +20 -2
  20. package/src/host/cpu-state.js +17 -0
  21. package/src/host/gametank-acp-state.js +53 -0
  22. package/src/http/skill-doc.js +10 -6
  23. package/src/mcp/tools/audio.js +1 -1
  24. package/src/mcp/tools/cart-parts.js +76 -0
  25. package/src/mcp/tools/lifecycle.js +1 -1
  26. package/src/mcp/tools/platform-tools.js +9 -1
  27. package/src/mcp/tools/platforms.js +46 -10
  28. package/src/mcp/tools/toolchain.js +35 -10
  29. package/src/platforms/gametank/lib/gt/audio/acp_image.bin +0 -0
  30. package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.c +55 -0
  31. package/src/platforms/gametank/lib/gt/audio/audio_coprocessor.h +34 -0
  32. package/src/platforms/gametank/lib/gt/audio/audio_fw.asm +223 -0
  33. package/src/platforms/gametank/lib/gt/audio/audio_fw_blob.s +8 -0
  34. package/src/platforms/gametank/lib/gt/audio/instruments.c +79 -0
  35. package/src/platforms/gametank/lib/gt/audio/instruments.h +25 -0
  36. package/src/platforms/gametank/lib/gt/audio/music.c +370 -0
  37. package/src/platforms/gametank/lib/gt/audio/music.h +35 -0
  38. package/src/platforms/gametank/lib/gt/audio/note_numbers.h +132 -0
  39. package/src/platforms/gametank/lib/gt/audio/scaled_sines.raw +0 -0
  40. package/src/platforms/gametank/lib/gt/audio/sine_256_-63_63.bin +0 -0
  41. package/src/platforms/gametank/lib/gt/banking.c +29 -0
  42. package/src/platforms/gametank/lib/gt/banking.h +8 -0
  43. package/src/platforms/gametank/lib/gt/banking2.s +41 -0
  44. package/src/platforms/gametank/lib/gt/crt0.s +102 -0
  45. package/src/platforms/gametank/lib/gt/draw_logo.s +55 -0
  46. package/src/platforms/gametank/lib/gt/feature/persist/persist.c +103 -0
  47. package/src/platforms/gametank/lib/gt/feature/persist/persist.h +13 -0
  48. package/src/platforms/gametank/lib/gt/feature/random/random.c +40 -0
  49. package/src/platforms/gametank/lib/gt/feature/random/random.h +18 -0
  50. package/src/platforms/gametank/lib/gt/feature/text/text.c +111 -0
  51. package/src/platforms/gametank/lib/gt/feature/text/text.h +25 -0
  52. package/src/platforms/gametank/lib/gt/gametank.c +12 -0
  53. package/src/platforms/gametank/lib/gt/gametank.h +80 -0
  54. package/src/platforms/gametank/lib/gt/gametank_logo.inc +393 -0
  55. package/src/platforms/gametank/lib/gt/gen/assets/assets_index.h +9 -0
  56. package/src/platforms/gametank/lib/gt/gen/assets/sdk_default.h +5 -0
  57. package/src/platforms/gametank/lib/gt/gen/bank_nums.h +11 -0
  58. package/src/platforms/gametank/lib/gt/gen/modules_enabled.h +4 -0
  59. package/src/platforms/gametank/lib/gt/gen/modules_enabled.inc +4 -0
  60. package/src/platforms/gametank/lib/gt/gfx/draw_direct.c +132 -0
  61. package/src/platforms/gametank/lib/gt/gfx/draw_direct.h +75 -0
  62. package/src/platforms/gametank/lib/gt/gfx/draw_queue.c +177 -0
  63. package/src/platforms/gametank/lib/gt/gfx/draw_queue.h +35 -0
  64. package/src/platforms/gametank/lib/gt/gfx/draw_util.s +157 -0
  65. package/src/platforms/gametank/lib/gt/gfx/gfx_sys.c +43 -0
  66. package/src/platforms/gametank/lib/gt/gfx/gfx_sys.h +46 -0
  67. package/src/platforms/gametank/lib/gt/gfx/sprites.c +216 -0
  68. package/src/platforms/gametank/lib/gt/gfx/sprites.h +41 -0
  69. package/src/platforms/gametank/lib/gt/init.c +9 -0
  70. package/src/platforms/gametank/lib/gt/input.c +26 -0
  71. package/src/platforms/gametank/lib/gt/input.h +20 -0
  72. package/src/platforms/gametank/lib/gt/interrupt.s +67 -0
  73. package/src/platforms/gametank/lib/gt/vectors.s +14 -0
  74. package/src/platforms/gametank/lib/gt/wait.s +53 -0
  75. package/src/platforms/gba/MENTAL_MODEL.md +22 -1
  76. package/src/playtest/playtest.js +174 -26
  77. package/src/playtest/resampler/build.sh +19 -0
  78. package/src/playtest/resampler/index.mjs +75 -0
  79. package/src/playtest/resampler/resampler.c +129 -0
  80. package/src/playtest/resampler/resampler.mjs +2 -0
  81. package/src/playtest/resampler/resampler.wasm +0 -0
  82. package/src/toolchains/arm-none-eabi-gcc/gcc.js +39 -188
  83. package/src/toolchains/asar/asar.js +10 -15
  84. package/src/toolchains/cc65/cc65.js +82 -92
  85. package/src/toolchains/cc65/da65.js +12 -17
  86. package/src/toolchains/cc65/preset-resolver.js +13 -2
  87. package/src/toolchains/cc65/presets/gametank/gametank.h +80 -0
  88. package/src/toolchains/cc65/presets/gametank/sdk.cfg +32 -0
  89. package/src/toolchains/cc65/presets/gametank/sdk.crt0.s +61 -0
  90. package/src/toolchains/cc65/presets/gametank/sdk.vectors.s +11 -0
  91. package/src/toolchains/cc65/presets/gametank/single-bank.cfg +28 -0
  92. package/src/toolchains/cc65/presets/gametank/single-bank.crt0.s +71 -0
  93. package/src/toolchains/cc65/presets/gametank/single-bank.vectors.s +12 -0
  94. package/src/toolchains/common/c-build.js +109 -0
  95. package/src/toolchains/common/gcc-toolchain.js +164 -0
  96. package/src/toolchains/common/wasm-tool.js +101 -0
  97. package/src/toolchains/dasm/dasm.js +12 -18
  98. package/src/toolchains/gba-c/gba-c.js +253 -305
  99. package/src/toolchains/genesis-c/genesis-c.js +196 -225
  100. package/src/toolchains/index.js +58 -4
  101. package/src/toolchains/m68k-elf-gcc/gcc.js +39 -202
  102. package/src/toolchains/mips-c/mips-c.js +68 -78
  103. package/src/toolchains/mips-elf-gcc/gcc.js +55 -118
  104. package/src/toolchains/rgbds/rgbds.js +7 -19
  105. package/src/toolchains/sdcc/sdcc.js +35 -26
  106. package/src/toolchains/sh-c/sh-c.js +44 -52
  107. package/src/toolchains/sh-elf-gcc/gcc.js +55 -110
  108. package/src/toolchains/sjasm/sjasm.js +10 -14
  109. package/src/toolchains/snes-c/snes-c.js +125 -150
  110. package/src/toolchains/tcc816/tcc816.js +10 -15
  111. package/src/toolchains/vasm68k/vasm68k.js +11 -16
  112. package/src/toolchains/wladx/wladx.js +5 -17
  113. 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). Accept a project-relative or bare name; it becomes the single
981
- // entry source. Without it, auto-detect main.c / main.s / main.asm.
982
- const entryName = opts.entry ? path.normalize(opts.entry).replace(/^[./]+/, "") : null;
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 exists = files.some((f) => f.name === entryName) ||
985
- subAssets.some((a) => a.rel === entryName);
986
- if (!exists) {
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}. Found top-level: ` +
989
- `${files.map((f) => f.name).join(", ") || "(none)"}.`
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 === entryName) continue;
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
@@ -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