[23:03] I was just going to describe the format from the ground up [23:03] all right [23:03] N-SPC is a tracker type of music driver [23:04] Used in lots of first party Nintendo Super Nintendo games [23:04] If you learn how to use it [23:04] you can potentially import music and instruments from other games that use the N-SPC driver [23:04] e.g. you could take music from Super Mario All Stars and implant it into Kirby Super Star [23:04] [DSO] Is there a quick way to find where that data is stored? [23:04] DSO: yes [23:05] That requires a general understanding of how the SPC <---> SNES communication works [23:05] If i'm looking at a new game [23:05] I want to know where the SPC driver is at [23:05] Now, the catch is that the N-SPC drivers for each game are not *identical* [23:05] but they're pretty close [23:06] Hold on [23:07] Since most people here are metroid hackers [23:07] I'm going to use Brinstar1.spc as an example [23:07] It's the green brinstar theme [23:07] (pink too) [23:07] SPC drivers almost always look like this: [23:08] two hex bytes [23:08] 20 CD [23:08] that's the start of the one in Super Metroid [23:08] Since that's the start of the driver [23:08] we can easily search for that in the rom itself [23:09] But you will likely find more than one instance of "20 CD" [23:09] in the rom [23:09] So what you do is take a few more bytes [23:09] in this case [23:09] 20 CD CF BD E8 00 5D AF [23:09] Should be sufficient for super metroid... [23:09] *checks* [23:10] Yeah [23:10] in a hex editor, that sequence of bytes only shows up once [23:10] Let me back up a second and say taht the "driver" is a term that refers to code that runs on the SPC-700 [23:10] The SPC-700 is a CPU separate from the SNES's main CPU [23:11] So if we find this data, we have only found the code that the SPC-700 runs [23:11] However, in most N-SPC games, the SPC related data is all lumped together [23:11] you find the driver, you find the rest of the music data [23:11] This is true of Link to the Past and Super Metroid, at the very least [23:11] I imagine it's the same for Super Mario Kart, etc [23:13] Generally speaking the 20 CD will be aligned on a page boundary, like 0x100, 0x200, 0x300, ... etc [23:13] In Super Metroid's case, it ends up being at 0x1600 in the SPC's memory (The SPC has 64K of its own RAM) [23:13] I'm trying not to go over everyone's heads [23:13] If you have a question don't be afraid to interrupt but keep in mind I won't spend forever on it [23:14] Small correction: SPC files have a 0x100 byte header at the beginning so it's technically 0x1500 for Super Metroid, as far as the SPC RAM goes [23:14] moving on [23:14] Using Geiger's SNES9x debugger, one can then use read breakpoints to isolate all the music data [23:15] I would hope by now someone would have written out what all the offsets were for Super Metroid [23:15] I take it that's not the case? [23:15] If not we can go through it manually [23:17] The nice thing about N-SPC data from nintendo [23:17] is that it's easy to break apart [23:17] at least on the ROM side [23:18] I might have to take this a little slow [23:18] But it's still fairly easy [23:18] so... starting [23:18] The location of the driver in the ROM is 0x278108 [23:18] agreed? [23:18] (no header) [23:19] This process should be fairly repeatable on other games [23:19] Since the driver is a logical unit [23:19] that is, a "chunk" [23:19] the start of it is just that, the start of a chunk [23:19] so in the ROM, we look to the left of that 20 CD [23:19] and what do we spy but a sequence like this [23:19] E2 41 00 15 [23:20] This is two 16-bit numbers [23:20] that tells us important information [23:20] 1. The length of the chunk is 0x41E2 bytes [23:20] 2. The location in the SPC's RAM that it will be transmitted to is 0x1500 [23:21] For the mathematically inept, 64K of RAM ranges from 0x0000 to 0xFFFF, and that's it [23:21] anyways, this chunk will be written to 0x1500 and will stop at 0x56E1 [23:22] The length of the "driver" "chunk" varies from game to game, as does its contents [23:22] But the music data is all basically the same format [23:22] the drivers usually differ in how they do sound effects, not music [23:22] Super Metroid has an unusually long driver chunk for an N-SPC game [23:22] To me, that tells me that it has a very complex sound effects system [23:23] Which makes sense, given its late release date and how cool most of the game sounds [23:23] Sound effect wise [23:23] Kejardon would probably have more info on that [23:23] Anyways [23:23] [DSO] He mentions some stuff on that in http://jathys.zophar.net/supermetroid/kejardon/SPCRamMap.txt I think [23:23] Well if you can locate it in that document [23:23] please share [23:24] i don't have time at the moment to go through it [23:24] In your hex editor... [23:24] we want to skip 0x41e2 bytes forward [23:24] there we will find the next chunk [23:25] These chunks are usually consecutively laid out in the ROM [23:25] That will bring us to ROM address 0x27C2EA [23:26] You should see the following bytes at that location [23:26] 93 0C 20 58 0E 53 .... [23:26] speak up if yours is not the same [23:26] I don't want to get off on an incorrect tangent [23:26] so far so good [23:26] What this would tell us [23:27] [DSO] 93 0c 20 58 means it's $0C93 bytes long and going in $5820? [23:27] ^ what he said [23:27] length is 0c93, goes to --yeah [23:27] show off [23:27] The real issue, is that we don't know what this data is [23:27] But we should make a note that it exists [23:27] it's clearly relevant [23:27] So we continue moving on [23:28] someone should compile a data sheet from this [23:28] so other hackers can use it [23:28] So from the 0E byte [23:28] we jump 0x0C93 bytes forward [23:28] And arrive at location 0x27CF81 [23:29] This next chunk is 0x00A0 bytes long, and gets stored to 0x6D00 [23:29] [DSO] um [23:29] yes? [23:29] [DSO] Isn't 27C2EA + C93 27CF7D? [23:30] you're right it is [23:30] but we need to jump from the start of the previous chunk [23:30] which would be 4 bytes after 27C2EA [23:30] the length and SPC addresses don't count as part of the chunk [23:30] b/c they're not going to be written into the SPC RAM [23:31] ‚lake sense [23:31] yeah [23:32] What it's saying is 0x0C93 bytes get written to location 0x5820, and after that are our 0x0C93 bytes to write [23:32] so we need to jump from the start of the actual chunk [23:32] not the .... "header" data [23:32] Anyways [23:32] right [23:32] We're going to jump again [23:32] this time from 0x27CF85 in the rom [23:33] (note again I incremented by 4 bytes from 0x27CF81), which is what confused DSO [23:33] so we jump ahead 0xA0 bytes [23:33] arrive at 0x27D025 [23:34] At this point, this is probably getting boring [23:34] but it will pay off [23:34] will anyone volunteer to compile the results later? [23:34] I'm going to skip to my documentation of the Super Metroid driver [23:34] the specifics of the driver tell you what each chunk does [23:35] [DSO] Question [23:35] k [23:35] [DSO] Some enemy sound effects change when you change the song in Super Metroid, does this mean that these songs are in a different chunk? [23:36] Well... when you say the sound effects change [23:36] I'm not really sure what you mean [23:36] you mean the types of sound effects? [23:36] Or the samples used to play them? [23:36] DSO, I don't think we're there yet [23:36] In any case [23:37] Songs and sound effect data don't have to be in the same chunk [23:37] when the game changes songs, it loads different instrument samples, sometimes enemies use those samples [23:37] [DSO] Samples probably [23:37] But if it loads a new song [23:37] chances are it's loading new ADPCM samples [23:37] which will in turn affect the sound effects [23:37] taht's something you guys will have to figure out [23:37] but yeah, we're not there yet [23:37] This is mostly a tutorial on how to locate music data and change it [23:38] Not sound effects [23:38] I know how to do that for LTTP [23:38] but I'd be lost in Super Metroid (sfx) [23:38] Anyways [23:38] Where were we [23:39] I'm at 0x27D025 [23:39] This gives us a header with the following data: [23:39] 0x91E0 bytes long, written to address 0x6E00 in the SPC [23:39] So like good little boys we skip ahead over this again [23:40] To 0x286209 [23:40] Now here's where the buck stops [23:40] We've hit a block with length 0x0000 [23:40] This is how the SNES CPU knows to stop transmitting data to the SPC [23:40] so we've covered quite a lot of terrain in the ROM [23:41] nearly two 32K banks of data [23:41] So I'll bust out my Super Metroid documentation [23:41] to see if it has info on these chunks [23:42] Okay, I don't [23:42] but I have a decent memory [23:42] so I'll just say what they are if I remember [23:42] [DSO] Kej has a bit of stuff on it it looks like [23:42] [DSO] 1500 - 56E1 is the main SPC engine. Copied from ROM at CF:8108 (278108). Some sections may be changed [23:42] [DSO] 1B62 - 1B9F is a jump table of sorts; Song data is interpreted with this. Not changed. [23:42] [DSO] 1E1D - 1E31 is panning volume multipliers. Not changed AFAIK. [23:42] [DSO] 1E32 - 1E51 is FIR coefficients. 4 groups of 8 bytes. Seems like it'd be changable, but not changed AFAIK [23:42] [DSO] 1E66 - 1E7F is the pitch table. (085F 08DE 0965 09F4 0A8C 0B2C 0BD6 0C8B 0D4A 0E14 0EEA 0FCD 10BE) [23:42] [DSO] 5800 - 5807 Note Sound Length percents [23:42] [DSO] 5808 - 5817 Note Volume percents? [23:42] [DSO] 581E - 5??? Song start addresses for 40. Maximum possible is 80, but usually only 6-8 are used. [23:42] [DSO] 5??? - ???? Song note data is stuck here, right after the end of the song start addresses. [23:42] [DSO] 6C00 - 6CE9 (Not certain about end address) 6 byte entries for 18F9. Voice Source #, ADSR1, ADSR2, Gain, and then two bytes stuck in 0220+x (x = 2*channel). Seems to have 1 entry per source #. [23:42] [DSO] 6CEA - 6CFF Unused? [23:42] [DSO] 6D00 - 6DFF is the sample table. Seems to stop at 6D96 (though 6C00 suggests 6D9C). *Must* stop by 6DA8 - that's all the table at 6C00 can support. [23:42] [DSO] ???? - F??? Instrument sample data. Pointed to by 6D00 sample table. [23:43] Okay, hold on a sec [23:44] The last chunk was really large [23:44] 0x91E0 bytes, to be exact [23:44] usually a chunk that big will be your sample (ADPCM) data [23:44] that's what most of you would refer to as "instruments" [23:44] It's sound data that has been prerecorded before being inserted into the game [23:45] and it's manipulated to product sound effects, music, etc [23:45] *produce [23:45] This meshes with Kej's data [23:45] because he says that the sample table is at 6D00-6DFF [23:45] The sample usually is right before the sample data, but not necessarily [23:46] *the sample table [23:46] *the sample table usually is right... [23:47] Now, Kejardon is not the word of God, so some of his notes don't really mesh with what I know, but I'll take his word for most of them [23:47] let's go to the previous chunk [23:48] That was 0x00A0 bytes, written to 0x6D00 [23:48] well... there's your chunk that describes the sample table [23:48] 6D00 - 6DFF is the sample table. Seems to stop at 6D96 (though 6C00 suggests 6D9C). *Must* stop by 6DA8 - that's all the table at 6C00 can support. [23:49] I don't really want to get into an indepth discussion of the sample table [23:49] but let's look at some of the data in it just to make sense of it [23:49] The sample table is a table of "pointers" to the ADPCM samples in the SPC RAM [23:49] Each entry is 4 bytes [23:49] the first two bytes specify the starting point of the sample [23:49] the second two bytes specify the loop point of the sample [23:50] Let's look at the first two entries in the sample table [23:50] at 0x27CF85 you'll see 00 6E C4 73 C4 73 88 79 [23:51] So the first four bytes correspond to "instrument" 1 [23:51] erm. "instrument" 0 [23:51] The sample starts at 0x6E00 and loops at 0x73C4 [23:51] My intuition tells me that this sample doesn't loop at all as its end point is the same as the start of the next sample [23:52] "instrument" 1 starts at 0x73C4 and loops at 0x7988 [23:52] I don't really follow the logic there, but if you say that's what it means, then okay [23:52] (about loop point = next sample, so must not loop) [23:52] Looped samples are something I don't want to get into at the moment [23:52] np [23:52] b/c well be dealing with the DSP at that point [23:53] a basic description would go as follows [23:53] [DSO] Does it mean instrument 0 and 1 play together? [23:53] The sample is a waveform [23:53] which can be very short or very long [23:53] DSO: no [23:53] let's say that instrument 0 is a piano [23:53] or rather, a recording of a piano key, either real, or synthed [23:53] when you hit a piano key [23:53] It makes a percussive noise when your finger first strikes it [23:54] but the sound it makes when you hold it down, is different from the sound it makes when you hit it, yes? [23:54] [ [hit] [held sound] ] [23:55] ^ let's say that the hit portion lasts 0.1 seconds [23:55] and the held sound part lasts 0.5 seconds [23:55] when you input your instrument data, you'd want to make this sample table up in a way that tells it what byte the held sound starts at [23:56] otherwise if you loop the sample, it will sound like someone hittting a piano key over and over and over again [23:56] rather tahn the sound of someone holding a piano key [23:56] does that not make sense to anyone? [23:58] that makes sense actually [23:59] some samples in the game don't actually ever get used long enough to play "held" notes and the programmers didn't give them that data [23:59] right [23:59] some samples are one offs [23:59] they aren't meant to loop [23:59] so if you tinker with the sound engine and try to make it use one, it sounds like the "hitting over and over again" [23:59] so the loop position is just set to the end of the sample [23:59] yeah, and now I know why, neato [23:59] basically, yeah [23:59] does this mean that any note would repeat if you let it play long enough? [23:59] if you set the base address to the same address as the loop address [00:00] you really will be doing the whole sample over and over again [00:00] e.g. 0x6E00 then 0x6E00 in this case [00:00] ah, ok [00:00] acheron: that's more getting into ADSR settings [00:00] i don't want to get into that right now [00:00] but if it loops, it's told at some point to jump into the sample at an appropriate point [00:00] sorry, carry on [00:00] you can make a sample play forever with aDSR [00:00] *ADSR [00:00] but it won't do that by default [00:01] read anomie's DSP guide if you want to know how that stuff works [00:01] it's very thorough [00:01] but at times hard to understand [00:01] anyways [00:01] so we know what that chunk did [00:01] moving backwards again [00:02] 0x27C2EE [00:02] which is the chunk that will be written to 0x5820 [00:03] according to Kej [00:03] this is the song note data [00:03] what he means, is that this is the tracker data [00:03] this is the song data! [00:03] It consists of commands to play musical notes, to change volume, and a shitload of other things [00:03] this is the stuff we're interested in [00:04] Now, as far as we know, this is only one set of song data [00:04] there's probably others in the ROM nearby to the chunks we're aware of [00:04] But! [00:04] We now know where the song data is read from in the SPC RAM [00:04] So someone pick a super metroid song [00:04] [DSO] Maridia1 [00:04] Is one your hear after blowing up the tube? [00:05] [DSO] Yeah, the one you hear when you first get into Maridia [00:05] well [00:05] in my set it's Maridia2.spc [00:05] If you know where the tube you blow up is [00:05] just go two screens up from that [00:05] load the spc file that corresponds to that in your hex editor [00:06] (in mind Maridia1.spc is not the one you're thinking of) [00:06] *in my set [00:06] [DSO] I said 1 simply because it's the first one you hear [00:06] I'm just clarifying [00:06] so we're all in the same file [00:07] to be totally clear, it's not the music you'll head in the room right before draygon [00:07] I've opened up my file in my hex editor [00:07] for convenience sake i'm going to chop off the 0x100 byte header [00:07] and save it as a different file name [00:07] like Maridia_test.spc [00:07] [DSO] Where did you get the spc file? [00:07] Probably zophar.net [00:07] ages ago [00:08] so I do some checking [00:08] and I look for 20 CD [00:08] to make sure the driver's at 0x1500 [00:08] low and behold, it is! [00:08] did I miss something? how do we know where maridia2.spc is? [00:08] Acheron: you'd have to have the spc set [00:08] I assumed you had it [00:08] snesmusic.org/v2/ [00:08] if you don't [00:09] oh [00:09] I'll wait but please hurry [00:09] go on for now, I can catch up later [00:09] I'm logging this [00:09] Anyway, the point of chopping off the header was to make sure that the 0x0000 in the file was the same as 0x0000 in SPC RAM [00:09] that's what SPC files are, they're dumps of the SPC's RAM [00:10] along with the DSP (digital sound processor) variables [00:10] from that an SPC player can begin playing the music [00:10] * Acheron can't connect to snesmusic.org, site seems to be down [00:10] zophar.net works too [00:10] anyways [00:10] [DSO] So I could just dump the SPC with SNES9x? [00:10] If you go to 0x5820 in the SPC file [00:11] You should see the following [00:11] 0E 53 6E 54 69 55 97 56 ... [00:11] what we want to do is see if we can locate this data in the ROM [00:12] If not, we'll have to be slightly more clever [00:12] [DSO] 27C2EE? [00:13] headers for spc always = 0x0100? [00:13] hehe [00:13] that works [00:13] that happens to match the chunk we were looking at in the ROM earlier! [00:13] no surprise there [00:13] One thing to keep in mind is that N-SPC can store more than one song in RAM at a time [00:14] In Super Metroid, it usually only keeps 5 songs in RAM at a time (SPC RAM) [00:14] But a game like Zelda LTTP keeps like... 10-14 songs in RAM at a time [00:14] It's just a different way of utilizing the engine [00:14] LTTP emphasizes the ability to change the song on the fly [00:14] whereas Super Metroid probably uses higher quality, larger samples to produce better music [00:14] But since the sequence data and the sample data have to be in RAM at the same time [00:15] there's always a trade off [00:15] A game like Chrono Trigger only keeps *1* song in SPC memory at a time [00:15] and afaik, doesn't keep any sound effects in RAM [00:15] as in, it streams them [00:15] But CT is pretty advanced [00:15] pushes the system pretty hard to its limit [00:18] Anyways [00:18] It's kind of hard with most spc players to change the song [00:18] I was going to try to show youse guys how to do that [00:18] gimme a minute or two [00:19] The problem is that they don't simulate input from the SNES CPU to the SPC [00:19] or rather they do... [00:19] but I gotta remember where to do it [00:24] I guess I cant' change it, not with my plugin anyways [00:26] The point is that a SNES side variable will control which song is currently playing [00:26] I look at the Maridia spc file to find out the number of the song that was playing [00:26] that's 06 [00:27] where can you find that? [00:27] At locations 0x0000, 0x0004, and 0x0008 in RAM in the SPC file [00:29] bah [00:29] I'm suffering from a lack of good Super Metroid roms / savestates at the moment [00:29] collateral damage from Redesign I guess [00:29] anyways [00:29] Since it's song 6 [00:30] We look at the bytes at 0x5820 [00:30] and we skip over 6 times 2 bytes [00:30] b/c these are all pointers to the data for each song [00:30] (pointers are two bytes) [00:30] We should end up at 0x582C in the SPC file [00:31] the data there is 5A 58 [00:31] this means we need to go to 0x585A [00:31] to get to the rest of the song data [00:31] If you haven't noticed yet, the SPC-700 is also little endian, so you have to reverse the bytes to figure out the pointers [00:32] So we go to 0x585A [00:32] We see 7D 5F, which is yet another pointer to 0x5F7D [00:32] Note that this data is called "part" data [00:32] some songs have multiple parts [00:33] Which are organizational in nature [00:33] how do we know where the pointing ends? [00:33] They handle looping, mainly [00:33] we'll get there [00:33] hold on [00:33] okies [00:33] [DSO] I remember hearing something about this [00:33] go to 0x5F7D [00:35] hrm... I might be confusing myself a tad bit [00:35] hold on [00:38] anyways [00:38] If you follow this data [00:38] At 0x5F7D [00:38] you should find the following bytes [00:38] FA 27 E7 0C E5 B4 .... etc [00:38] is that what you all find? [00:39] yeah [00:40] okay [00:40] This to me, looks like what I call track data [00:41] It goes "song data", which is a pointer to "part data" which could have more than one pointer, and then each part points to "track data" [00:41] this might not have been the best example as I can only find one track [00:41] but I'll explain anyway [00:41] observe [00:41] Command_Jump_Table: [00:41] 0EEA: dw $0C66 ; command E0(1) (instrument) [00:41] 0EEC: dw $0CBF ; command E1(1) (pan) [00:41] 0EEE: dw $0CCD ; command E2(2) (pan slide) [00:41] 0EF0: dw $0CE6 ; command E3(3) (vibrato) [00:41] 0EF2: dw $0CF2 ; command E4(0) (vibrato off) [00:41] 0EF4: dw $0D0D ; command E5(1) (global volume) [00:41] 0EF6: dw $0D1C ; command E6(2) (global volume slide) [00:41] 0EF8: dw $0D2E ; command E7(1) (tempo) [00:41] 0EFA: dw $0D33 ; command E8(2) (temp slide) [00:41] 0EFC: dw $0D45 ; command E9(1) (global transpose) [00:41] 0EFE: dw $0D48 ; command EA(1) (tranpose) [00:42] 0F00: dw $0D4C ; command EB(3) (tremelo) [00:42] 0F02: dw $0D58 ; command EC(0) (tremelo off) [00:42] 0F04: dw $0D79 ; command ED(1) (channel volume) [00:42] 0F06: dw $0D82 ; command EE(2) (volume slide) [00:42] 0F08: dw $0D9F ; command EF(3) (call loop) [00:42] 0F0A: dw $0CFD ; command F0(1) (vibratostep (????????) [00:42] 0F0C: dw $0D5B ; command F1(1) (pitch slide to) [00:42] 0F0E: dw $0D5F ; command F2(1) (pitch slide from) [00:42] 0F10: dw $0D75 ; command F3(0) (pitch slide stop) [00:42] 0F12: dw $0D9B ; command F4(1) (fine tune) [00:42] 0F14: dw $0DC2 ; command F5(3) (echo control) [EON, EVOLL, EVOLR] [00:42] 0F16: dw $0DF9 ; command F6(0) (echo silence) [EDL = 0, EVOLL = 0, EVOLR = 0] [00:42] 0F18: dw $0E00 ; command F7(3) (Echo and Filters) [sets EDL, ESA, EFB, VxFIR] [00:42] 0F1A: dw $0DD8 ; command F8(3) (echo volume slide) [00:42] 0F1C: dw $0E9B ; command F9(3) (pitch slide) [00:42] 0F1E: dw $0E68 ; command FA(1) (percussion offset) [00:42] ; Num_Parameters_For_Commands: [00:42] 0F20: db $01 ; command E0 number of parameters [00:42] 0F21: db $01 ; command E1 number of parameters [00:42] 0F22: db $02 ; command E2 number of parameters [00:42] 0F23: db $03 ; command E3 number of parameters [00:42] 0F24: db $00 ; command E4 number of parameters [00:42] 0F25: db $01 ; command E5 number of parameters [00:42] 0F26: db $02 ; command E6 number of parameters [00:42] 0F27: db $01 ; command E7 number of parameters [00:42] 0F28: db $02 ; command E8 number of parameters [00:42] 0F29: db $01 ; command E9 number of parameters [00:42] 0F2A: db $01 ; command EA number of parameters [00:42] 0F2B: db $03 ; command EB number of parameters [00:42] 0F2C: db $00 ; command EC number of parameters [00:42] 0F2D: db $01 ; command ED number of parameters [00:42] 0F2E: db $02 ; command EE number of parameters [00:42] 0F2F: db $03 ; command EF number of parameters [00:42] 0F30: db $01 ; command F0 number of parameters [00:42] 0F31: db $03 ; command F1 number of parameters [00:42] 0F32: db $03 ; command F2 number of parameters [00:42] 0F33: db $00 ; command F3 number of parameters [00:42] 0F34: db $01 ; command F4 number of parameters [00:42] 0F35: db $03 ; command F5 number of parameters [00:42] 0F36: db $00 ; command F6 number of parameters [00:43] 0F37: db $03 ; command F7 number of parameters [00:43] 0F38: db $03 ; command F8 number of parameters [00:43] 0F39: db $03 ; command F9 number of parameters [00:43] 0F3A: db $01 ; command FA number of parameters [00:43] So [00:43] hopefully you can all read that [00:43] The first command in the track data is FA [00:43] so we look at the above table [00:43] FA(1) [00:43] percussion offset [00:43] This is the N-SPC driver's command set [00:43] most SPC drivers have a command set [00:43] Squaresoft had one [00:43] almost everyone has something like this [00:44] when it comes to playing back music [00:44] i.e. tracker data [00:44] so the question at this point, is does this data make sense? [00:44] FA 27 would say [00:44] "play drum number 27" [00:44] now, given that there's no drums in the Maridia song we're looking at [00:44] chances are we've made a mistake [00:44] so we backtrack [00:44] And even do a little spc editing [00:44] let me get it set up [00:45] You'll have to reload the original maridia.spc file and make a copy of it [00:45] it will need the header [00:45] In this file I'm going to go and edit the 5A 58 that points to the song, to something else [00:46] some nonsense number [00:46] if the song refuses to play, I know I've hit the Maridia song [00:46] Note that in the unmodified spc file, the offset will be at 0x592C rather than 0x582C [00:51] anyways [00:51] verified that it was actually the previous entry [00:51] a song number of 06 means we need to go to the 05th entry in the song table [00:51] that's why nothing made sense [00:51] (because a song value of 00 indicates to not change the song at all!) [00:51] trying to get back on track [00:52] back to the truncated (headerless spc file) [00:52] at 0x582A in that file [00:52] we see 2A 58 [00:52] sorry [00:52] 29 60, which is a pointer to 0x6029 [00:53] we follow that pointer and see 60 43 33 60 FF 00 [00:53] This is the part data [00:54] 43 60 (0x6043) is a pointer to part 0 [00:54] (Please note 60 43 33 60 was supposed to be 43 60 33 60) [00:54] 33 60 (0x6033) is a pointer to part 1 [00:55] Now... what the fuck is FF 00 (0x00FF)? [00:55] afaik, or can remember, that just means to repeat the previous part indefinitely [00:55] Since the maridia song loops indefinitely [00:56] that makes sense [00:56] if it was 00 00.... I think it would probably just stop playing [00:56] some songs will do that, like Samus' Item pickup theme [00:56] And as a matter of course I just verified that it was 00 00 [00:57] I don't have full documentation of that laid out at the moment [00:57] Moving on [01:12] part 0 [01:12] is at 0x6043, as mentioned before [01:12] At this location is the "track data" [01:13] which consists of 8 "track pointers" [01:13] 7A 63 AE 63 E5 63 [01:14] and the rest are 00's [01:14] this means that the song uses 3 channels of the SPC [01:14] the first three, even [01:14] each pointer points to data for each channel [01:14] Now [01:14] this is only part 0, keep in mind [01:14] part 1 might use more channels [01:15] given how quiet that song is when it starts out [01:15] this seems to make sense [01:15] Let's look at the pointer for channel 0 [01:15] 0x637A [01:16] FA 27 E7 0F E5 32 E6 A0 96 E0 1F ... [01:16] Now we run into the same situation as earlier [01:16] FA 27 [01:16] what is this? [01:17] well... the best explanation I can give is that Super Metroid has a slightly different music driver than the others [01:17] unless it really is using the percussion command [01:17] LTTP doesn't ever use it [01:17] but super metroid might [01:17] Anyways [01:17] What FA 27 means is [01:18] Set the percussion offset to 27 [01:18] that means that samples 27 (instruments 27) and above are for use with the percussion subsystem [01:18] I dont' want to get into the percussion details [01:18] Btw I am contradicting myself from earlier [01:18] B/c I had forgotten what FA 27 did [01:18] moving on to the next bytes [01:19] E7 0F [01:19] (I'm also contradicting myself in that I no longer thing that the music driver is different from the others, I was just thinking out loud) [01:19] Let's look at the table I pasted in earlier [01:19] 0EF8: dw $0D2E ; command E7(1) (tempo) [01:20] command E7(1) in the syntax I've used indicates it takes one parameter [01:20] b/c there's a 1 in the parentheses [01:20] so this means, set the tempo of the song to 0F [01:20] chances are that if you change this byte [01:20] you'll hear a difference in tempo [01:21] but you'll have to use an unmodified spc file b/c spc players require the header to play [01:21] moving on [01:21] btw, channel 0 is the channel that usually has the configuration commands [01:21] you wouldn't set tempo on channel 1 and global volume on channel 0 [01:22] It just makes it easier that channel 0 has them all [01:22] but you could use the other channels to issue global commands that affet all channels if you wanted to [01:22] E5 32 is the next command [01:23] 0EF4: dw $0D0D ; command E5(1) (global volume) [01:23] this sets the over all volume of the SPC to 0x32 [01:25] E6 A0 [01:26] 0EF6: dw $0D1C ; command E6(2) (global volume slide) [01:26] ; Parameter info: byte1 - ticks it takes to get to target volume, byte 2 - target volume [01:26] this is all from Zelda_SPCv5.log on math.arc-nova.org [01:26] btw [01:26] As you can see, I can make sense of Super Metroid's music by making reference to Zelda's [01:26] even though the games were developed 3 game apart [01:27] What does the global volume slide do? [01:27] It has a target volume [01:27] I also forgot a parameter [01:27] it's E6 A0 96 [01:27] So we're trying to get to a volume of 0x96 [01:28] and the current volume is 0x32, remember [01:28] the driver will keep gradually increase the volume to 0x96 over 0xA0 ticks [01:28] the amount of time that 0xA0 ticks takes depends upon the tempo [01:28] I don't have exact calculations available [01:28] but I'm sure you could all figure it out if you really wanted to [01:28] point is, it's all relative [01:29] the tick is the smallest amount of time you can play a note [01:29] The SPC-700 has internal timers that can be set to different frequencies [01:29] that's how tempo is controlled [01:29] E0 1F is the next command [01:30] 0EEA: dw $0C66 ; command E0(1) (instrument) [01:30] So this says, set the instrument to 0x1F [01:30] I don't want to get into it yet [01:30] but "instruments" in N-SPC aren't the same thing as samples [01:31] "instruments" reference a sample but consist of additional configuration parameters [01:31] If you want your instrument to sound different, you configure the instrument table, which is a chunk we have not seen yet! [01:32] In a nutshell, it provides settings for ADSR, the sample to use, and a parameter to "tune" the sample to a certain note. [01:32] F4 96 is the next command [01:32] 0F12: dw $0D9B ; command F4(1) (fine tune) [01:33] it's a single parameter command that provides a fine tuning (pitch alteration) to the instrument [01:33] next command : EA 00 [01:33] 0EFE: dw $0D48 ; command EA(1) (tranpose) [01:33] transpose is a term that means to shift a tuning up or down one or more half notes [01:34] e.g. a transpose of 01 [01:34] would mean that all the old A notes would become A#'s [01:34] B flats would become C's [01:34] D#'s would become E's [01:34] etc [01:34] don't want to get mired in musical language [01:35] Anyways, setting the transpose to 00 means, there is no transpose! [01:35] This is merely initialization, to ensure that no transpose is being used, as it could make the song sound funky if one of the channels was out of tune [01:35] next command : ED 78 [01:35] 0F04: dw $0D79 ; command ED(1) (channel volume) [01:36] This sets the channel volume to 78 [01:36] There is global volume, and then there is channel volume [01:36] I hope it's pretty clear what the difference is [01:36] it can make one instrument sound quieter while others sound louder, etc [01:36] next command E1 0A [01:36] 0EEC: dw $0CBF ; command E1(1) (pan) [01:37] [DSO] Will global volume affect an instrument that has the lowest possible channel volume? [01:37] DSO: yes, it should [01:37] global volume is a base volume [01:37] It's kind of icky and complicated [01:37] and it works off a bunch of multipliers [01:37] To know the details you'd have to consult the code of the driver [01:37] when I say it's a base volume, I mean it's a base "multiplier" [01:38] e.g. if global volume is 05 and channel volume is 00 [01:38] channel volume is still 00 (I think) [01:38] because they get multiplied together [01:38] but as long as the channel is still audible on some level [01:38] the global volume will affect it [01:38] anyways, panning [01:39] panning is the balance of left and right volume in a stereo sound setup [01:39] The N-SPC has 20 levels of panning [01:39] 0 means that all the volume for the channel is in the left speaker [01:39] and 0x14 means that all the volume is in the right speaker [01:39] 0x0A is perfectly balanced pan, equal volume between the two speakers [01:40] An easy example is to listen to the final Lavos song in Chrono Trigger [01:40] like, the final fight [01:40] it pans left and right all the time [01:40] [DSO] It's also used for enemy sound affects probably [01:40] [DSO] effects* [01:40] yeah, LTTP uses panning [01:41] but only three levels of it [01:41] (far left, middle, and far right) [01:41] Not sure what Super Metroid does [01:41] Next command F5 07 46 46 [01:41] this is a rare 3 byte commands [01:41] *command [01:42] 0F14: dw $0DC2 ; command F5(3) (echo control) [EON, EVOLL, EVOLR] [01:42] this one involves a little knowledge of the DSP [01:42] basically [01:43] the first byte will get written to EON, which is the echo enable register on the DSP [01:43] 0x07 is a bit pattern [01:43] meaning, enable echo on channels 0, 1, and 2 [01:43] but, since we're using only channels 0, 1, and 2, this makes perfect sense [01:44] The second two bytes set the echo volume for the left and right speaker [01:44] since the echo sound gets mixed in after the rest of the sound has been generated [01:44] it can be indepdnently configured [01:44] *independently [01:44] As you probably noticed, a lot of these numbers for volume, panning, etc [01:44] are pretty arbitrary [01:44] they're not percentages [01:44] they're driver specific values [01:45] chrono trigger, for example, uses completely different numbers that provide a completely different scale of volume output [01:45] 7F in one might correspond to 4A in another [01:46] moving on [01:46] I know we're going through a lot of commands [01:46] but you won't see nearly as many on the other channels [01:46] this is all initialization [01:46] next command: F7 02 60 00 [01:46] 0F18: dw $0E00 ; command F7(3) (Echo and Filters) [sets EDL, ESA, EFB, VxFIR] [01:46] this one is getting even more hairy [01:47] This sets the EDL (echo delay) to 02 [01:47] what that means in layman's terms is how large the echo buffer is [01:47] setting EDL to whatever the hell you want is a bad idea [01:47] I suggest keeping it at whatever the game keeps it at [01:47] b/c the echo buffer uses SPC RAM [01:47] if set to too large a buffer, it will likely overwrite other data too! [01:48] memory usage is typically tight in SPC programming [01:48] so you will 99.999999% chance fuck something up [01:48] just follow the game's lead [01:48] set it no higher than the highest value you see [01:48] The second byte affects EFB (echo feedback) [01:49] I don't totally understand this register, but do understand that if you set it too high it can make your ears bleed [01:49] as the echo signal saturates and sounds like distortion from hell [01:49] Here it's set to 60 [01:49] *shrug* [01:49] apparently that works well enough [01:49] but it might not work well in another song [01:49] be careful and don't kill your ears [01:50] The third byte [01:50] sets the Fir Coefficients [01:50] Fir is part of the echo system [01:51] It's kind of like running the previous echo samples through a polynomial [01:51] it can create a different sound depending on how the Fir coefficients are configured [01:51] I don't totally understand this, see Anomie's doc if you have any questions (the DSP doc) [01:51] what this does [01:51] actually [01:51] is picks from a set of FIR coefficients [01:51] for example [01:51] in LTTP [01:51] it takes the byte that's passed in [01:51] (00 in this case) [01:52] and multiplies it by 8 [01:52] then uses it as an index to load from a table in SPC RAM [01:52] that table consists of FIR coefficients for each *channel* [01:52] one byte per channel [01:52] LTTP only has 4 different sets of FiR coefficients [01:52] so that's 0x20 bytes [01:53] But... I don't see why Super Metroid couldn't have more than 4 [01:53] that would require some investigation [01:53] I'm personally interested in modifying the N-SPC to allow input of arbitrary FIR coefficients from the SNES side [01:53] but I don't know if I'll ever get around to that [01:54] I think I might be able to implement a reverb type of effect... but anyways, moving on [01:54] ED 46 [01:54] sets channel volume to 46 [01:54] either my memory is bad, or we already set channel volume [01:54] Unfortunately stuff you see out in the field doesn't always make sense [01:54] so just roll with it [01:55] they generated this data with an automated tool most likely, I'm sure it wasn't the most intelligent tool ever [01:56] next command : EE A8 78 [01:56] 0F06: dw $0D82 ; command EE(2) (volume slide) [01:56] like the global volume slide [01:56] this sets the volume over the course of 0xA8 frames [01:56] and it will end up at 0x78 [01:56] (it started at 0x46 of course) [01:57] all right [01:57] I'm sure it's been 100% exciting so far [01:57] but we're going to move on to non commands [01:57] since the data stream I'm reading is no longer commands but notes and other data [01:57] okay [01:58] 48 7F A7 60 C8 E5 96 ... [01:58] note the lack of bytes that are 0xE0 and higher [01:58] until the E5 of course [01:59] 0xE0 and up are commands [01:59] the commands that are avaialble on each N-SPC driver can vary a light amount [01:59] LTTP is missing two SPC commands (FB and FC) [01:59] But afaik that's because you never pause the music in LTTP [01:59] it's always playing [02:00] Here's how it works [02:00] if the byte you come to is not a command [02:00] you look at it and see if it's <= 0x7F [02:00] in this case 48 is <= 0x7F [02:01] small code snippet [02:01] 0B9A: 30 20 BMI $0BBC ; if(track_byte & 0x80) goto $0BBC; [02:01] 0B9C: D5 00 02 MOV $0200+X,A ; else store the byte to $0200+X [02:01] that's SPC ASM [02:01] BMI is of course "branch if negative" [02:01] so if it ends up at 0B9C [02:02] that means that the byte was <= 0x7F [02:02] or, as expressed in the comments, (track_byte & 0x80) was zero [02:02] the question is, what is $0200+X? [02:02] ; $0200+X = note sustain time (when a voice is keyed on, this is how long it takes to reach release state) [02:03] note that $0200 could be something entirely different in Super Metroid's drivers [02:03] RAM addresses for things do not tend to be consistent across versions of the driver [02:03] but the N-SPC song data and format does! [02:03] so anyways [02:04] N-SPC implements a sustain time that is in addition to the DSP's sustain system [02:04] it basically means, set the percentage of the note you want to hold this for [02:04] e.g. setting it to 50% would totally cut the volume of the channel to 0 [02:04] after 50% of the time of the note had elapsed [02:04] let's say that was 0xA0 ticks and you're playing a C# [02:04] at 0x50 ticks [02:05] that C# cuts out [02:05] and you're left with silence on the channel [02:05] this actually caused me quite a bit of headache as you can't get 100% sustain in the N-SPC [02:05] and chrono trigger's engine can [02:05] so when I converted CT music to LTTP music [02:05] things sounded just slightly off [02:07] reviewing my notes a bit to make sure this was all correct... [02:08] cancel that [02:08] the first byte is the note "length" [02:09] i.e. the number of ticks [02:09] in this case [02:09] 0x48 ticks [02:09] notice there's no concept of quarter note / half note / whole note, etc [02:09] it's all in ticks [02:09] but you can always make up your own definitions [02:09] typically I see 0x60 as being like a whole note [02:09] iirc [02:10] anyways [02:11] what I said earlier about sustain still applied, but to the second byte [02:11] provided there is a second byte [02:11] the first byte and the second byte are optional [02:11] you can just play a note without setting a note lenght or sustain [02:11] and it will use the most recently set note length or sustain for that channel [02:11] this saves space in the tracker data [02:12] so if you're repeating a bunch of notes that are all the same length, you can just specify the pitch [02:12] (of each in succession) [02:12] anyways, the second byte, if present [02:12] goes as follows [02:12] it's 7F [02:13] another code snippet reveals the following: [02:13] 0B9F: 3F 5C 0C CALL get_track_byte ; grab the next byte. [02:13] 0BA2: 30 18 BMI $0BBC ; if(track_byte < 0) [02:13] 0BA4: 2D PUSH A [02:13] 0BA5: 9F XCN A [02:13] 0BA6: 28 07 AND A,#$07 [02:13] 0BA8: FD MOV Y,A ; Y = (XCN(A) & 0x07) [02:13] 0BA9: F6 96 3D MOV A,$3D96+Y ; A = one of {50,101,127,152,178,203,229,252} [02:13] 0BAC: D5 01 02 MOV $0201+X,A ; $0201+X = that result. what is this!!!? [02:13] 0BAF: AE POP A ; [02:13] 0BB0: 28 0F AND A,#$0F ; [02:13] 0BB2: FD MOV Y,A ; [02:13] 0BB3: F6 9E 3D MOV A,$3D9E+Y ; A = one of {25, 50, 76, 101, 114, 127, 140, 152, 165, 178, 191, 203, 216, 229, 242, 252} [02:13] 0BB6: D5 10 02 MOV $0210+X,A ; $0210+X is a note level volume modulator [02:13] 0BB9: 3F 5C 0C CALL get_track_byte ; retrieves a byte from the track data. [02:13] Of course this probably looks like gibberish [02:13] we take 7F [02:14] do an XCN on it [02:14] (exchange nybbles) [02:14] which forms F7 [02:14] then AND with 0x07 [02:14] then use it as an index by storing it to the Y register [02:14] so in our case [02:14] we'll be using $3D96 + 7, which is $3D9D [02:15] 252 (decimal) [02:15] so what the hell is this? [02:15] (per my comment in the file) [02:15] ; $0200+X = note sustain time (when a voice is keyed on, this is how long it takes to reach release state) [02:15] my documentation doesn't always match in all places ;) [02:16] so you've got 8 levels of sustain, indicated by the top nybble of the second byte [02:16] [DSO] I'm wondering [02:16] the bottom nybble provides 16 levels of volume control on the note [02:16] Meaning, this one particular note can sound louder, or softer than the channel volume [02:17] DSO:? [02:17] [DSO] Would it be possible to change the SPC driver mid game? [02:17] Yeah, you could [02:17] It could get hairy though [02:18] That's a pretty advanced topic, to be honest [02:18] your best bet would be to alter the N-SPC so that it can go back to the bootstrap ROM [02:18] which is a 0x40 byte area in the SPC's RAM [02:18] that contains the bootloader that handles the first SPC transfer before your custom driver starts working [02:18] CT's driver can go back to the boostram ROM, N-SPC can't, that I'm aware of [02:19] and I spent a sizeable amount of time studying N-SPC [02:19] anyways [02:19] so those two bytes are *completely* optional [02:20] next byte is A7 [02:20] now, after 3 hours of discussion [02:20] we arrive a freaking MUSICAL NOTE [02:20] HOLY SHIT [02:20] okay [02:21] So far we've covered bytes 0x00 through 0x7F, and 0xE0 through 0xFF [02:21] for the most part anyways [02:21] [DSO] So above 7F is musical notes? [02:21] 0x00 - 0x7F = note modifications, 0xE0 - 0xFF = commands [02:21] (though not all commands would be available in all drivers, and some in *NO* drivers) [02:21] 0x80 to 0xC7 are musical notes [02:22] each byte corresponds to a half step [02:22] if 0x80 is A [02:22] 0x81 is A# [02:22] 0x8C is also A [02:22] but an octave up [02:22] I don't have the exact layout [02:22] written down [02:22] b/c other people have written it down [02:22] lemme pull it up [02:23] [DSO] So the notes of the chromatic scale, based on whatever pitch you set the sample instrument at and stuff? [02:23] well... Matrixz has a document on it somewhere on the web [02:23] I can't find it on my computer at the moment [02:24] chromatic scale? [02:24] what exactly are you referring to? [02:24] I'm musically trained but I don't remember everything [02:24] it's been a while [02:24] [DSO] Chromatic scale = all the notes [02:24] [DSO] A A# B and so on until it loops to A again ect [02:26] pretty much [02:27] obviously you don't have a full piano [02:27] or maybe you do... [02:27] how many keys on a full piano? [02:27] 72? XD [02:27] [DSO] 84 [02:27] [DSO] I believe [02:28] well [02:28] anyways [02:28] that gives you 6 octaves [02:28] if I'm counting right [02:28] but global transpose can get you higher or lower than all that [02:28] *shrug* [02:28] it's a hairy situation [02:28] b/c if you set the pitch registers too high [02:28] you underflow [02:28] and your instrument is so low frequency [02:29] that you can't *hear* it [02:29] at all [02:29] your ears just can't hear it [02:29] importing music from CT this was one of my biggest problems [02:29] the instruments were tuned differently on those two platforms [02:29] so I'd take a sample from CT [02:29] and not know how to tune it in N-SPC properly [02:30] my instrument would be offkey, or too high, or too low [02:30] or inaudible [02:30] quite a clusterfuck [02:30] and the math formulas can suck [02:30] I want to make at some point, a tuning tool for N-SPC [02:30] anyways [02:30] 0xC8 - a rest [02:31] e.g. 70 C8 [02:31] a rest that lasts 0x70 ticks [02:31] 0xC9 - sustain [02:31] e.g. 70 A7 C9 [02:32] that amounts to 0xE0 ticks of whatever note A7 is [02:32] finally [02:32] 0xCA and above, up to 0xDF (inclusive) [02:32] these are percussion [02:33] as I said earlier, percussion doesn't necessarily have to involve drums [02:33] the idea behind the percussion system [02:33] is to not only play a note [02:33] but also change to a different sample, with just one byte [02:33] e.g. if you wanted to hit a hi-hat drum sound, then a bass drum immediately after that [02:33] you'd use the percussion system [02:33] earlier we saw FA 27 was the first command [02:34] this means that instruments 27 and up are considered part of the percussion system [02:34] an example in a moment [02:35] 0906: 3F 66 0C CALL $0C66 ; sets the instrument for this voice using an alternate method [02:35] ; doesn't seem to see much use. [02:35] ; you can use 0xCA through 0xDF to set the instrument index to [02:35] ; 0x00 through 0x15, respectively. [02:35] ; later games use this feature for percussion (drum) sets to switch [02:35] ; between different drum notes and ADSR values quickly. [02:35] 0909: 8D A4 MOV Y,#$A4 ; This is middle C, so a drum instrument always plays as middle C [02:35] ; (this of course doesn't take into account the tuning byte in the instrument table.) [02:35] ^ from the Zelda disassembly [02:35] anyways [02:35] if you know any drummers [02:35] you know they tune their drums before a performance [02:35] to a certain note [02:35] so the instrument table could configure two bass drums [02:35] but one at D [02:36] and another at G flat [02:36] or whatever [02:36] but you could switch between those two drums with a minimum of hassle using the percussion system [02:36] I honestly don't have much else to go over [02:37] that I can think of, at the moment [02:38] the loose ends are [02:38] how do I know when a track is complete [02:38] and how do parts work? [02:38] also, how do the other commands work? [02:38] any other loose ends? [02:38] [DSO] Not that I can think of, you'd know better than me [02:39] did you mention looping napkins? i haven't been here the whole time srt [02:39] well I meant questions you might have :P [02:39] XD [02:39] how do I loop a napkin? [02:39] [DSO] Do you have any experience importing samples from outside what's already in a ROM somehwere? [02:39] that's what I did for my CT imports [02:39] like how does it know when to loop back to a certain point in the track? [02:39] [DSO] I mean, like if I was going to record a keyboard [02:39] I imported them from the CT spc set directly to a target ROM [02:40] [DSO] Would it sound better to record just a C note, or a C chord? [02:40] DFPercush: that is either handled at the tracker level [02:40] or the part level [02:40] k [02:40] hold on [02:41] okay [02:41] 0F08: dw $0D9F ; command EF(3) (call loop) [02:41] now [02:41] I'm a little fuzzy on how this works [02:42] having messed with CT much more recently than Zelda [02:42] but [02:42] I think a call loop command [02:42] with the last parameter as zero [02:42] is equivalent to a "jump to this place" command [02:42] normally [02:42] e.g. [02:42] EF 00 63 03 [02:42] that would jump to location 0x6300 in the SPC RAM [02:43] and would do 3 iterations of that loop [02:43] (the end of the loop is a 0x00 byte) [02:43] 0x00 terminates a part, by the way [02:43] unless you're in a call loop [02:43] it's the exception to the 0x00 to 0x7F rule being note configurators [02:44] and when I say it terminates a part [02:44] it terminates the whole part [02:44] e.g. [02:44] let's say we've got 8 tracks [02:44] the last 7 channels have been configured to run for 1 minute [02:44] but channel 0 encounters a 0x00 byte (as a command) only 30 seconds into its playback [02:44] the whole part is over then1 [02:44] *then! [02:45] This is the thing I hate most about N-SPC [02:45] on the one hand it provides easy synchronization [02:45] hmm [02:45] which CT lacks [02:45] but it is also hard to tell when track data ends [02:45] so you have to tell it how many loops to run [02:45] just looking at it in hex [02:46] well [02:46] once a part is over [02:46] it continues to the next part [02:46] unless you specify a number of times to play that part [02:46] I think something like [02:46] 20 53 02 00 [02:46] then after that 20 54 FF 00 [02:47] I think that would play the track data at 0x5320 two times [02:47] as in, loop twice [02:47] being played 3 times all in all [02:47] then it would play the track data at 0x5420 indefinitely [02:47] as 0x00FF means to loop indefinitely [02:48] I don't remember the details on the parts very well [02:48] there's a couple of wacky special cases in there [02:48] special values that mean different things [02:48] ok that's fine [02:48] DSO: it would probably sound better to record a single C note [02:49] btw, found this in my SPC notes for Super metroid [02:49] 1b96: dw $1af1 ; 0xFA fast instrument? (drum beat according to bh89) [02:50] 1b98: dw $1af4 ; 0xFB (command does not exist in NSPC-Zelda but this command actually does nothing at all.) [02:50] 1b9a: dw $1af8 ; 0xFC channel sustain [02:50] 1b9c: dw $1afd ; 0xFD global sustain on [02:50] 1b9e: dw $1afe ; 0xFE global sustain off [02:51] those are the commands that weren't present in LTTP [02:51] (except for FA) [02:52] DSO: think about it, if you record a C chord, like a C major chord [02:52] C E G [02:52] you only have that one chord [02:52] you can play it on one channel [02:52] but it takes up a shitload of space for just one type of chord [02:53] you won't have C minor [02:53] C Eflat G [02:53] you won't have any other chords [02:53] It would be pretty pointless [02:53] all you'd have would be at transposable major chord [02:54] Of course, if you want a 3 or 4 note chord the other way you need to utilize 3 or 4 channels [02:54] to play the chord [02:54] there's always tradeoffs [02:54] but recording a chord as a sample is pretty bassackwards [02:54] especially with a limited RAM environment like the SPC-700 [02:54] ANY OTHER QUESTIONS? [03:02] typically the digital processing gets bad when you go above or below two octaves of the sampled frequency [03:02] which in most cases will be fine [03:02] if you've got to have a very low piano part and also a very high piano part [03:02] it's usually advisable to have two separate recordings of a piano key [03:03] one at a low pitch, and another at a high pitch [03:03] and just call them different instruments