Klax (Doom's Gate) ================== A music improvement to show similarities between thrash metal soundtracks of two games from the Nineties Produced by Damian Yerrick in September 2018 Klax's audio driver ------------------- The audio driver of Tengen's port of _Klax_ to NES heavily uses hardware sweep and hardware envelopes. The driver sets up a duty, volume, and sweep (for detune effect) and lets the hardware trigger a new note whenever the frequency is rewritten. I hand-decompiled some of the music sequence processing: ``` u8 cur_channel @0x04F5; u8 note_ticks_left[] @0x04C7; u8 cur_note[] @0x04CC; u16 channel_seq_pos[] @0x04D5; const u8 durations[] = {1, 2, 4, 8, 16, 32, 64} @0xA000; const u16 note_freqs[] @0xA30C; void set_ch_freq(u8 semitone_num) @A2E6; void play_next_note(void) @A291 { ptr_f7 = channel_seq_pos[cur_channel]++; Y = *ptr_f7; A = Y & 0xE0; if (A == 0xE0) { A = Y; A = func_A179(); if (A) set_ch_freq(A); return; } note_ticks_left[cur_channel] = durations[A >> 5]; A = Y & 0x1F; if (X != 3 /* noise */) { // A2D4 if (A >= 16) A -= 32; A += cur_note[cur_channel]; cur_note[cur_channel] = A; if (A != 1) set_ch_freq(A); } } else { if (A > 16) A |= 0x80; // loopnoise Set noise period to A and trigger } } ``` Thus bits 7-5 are log(note length), and bits 4-0 are a 2's complement signed interval in semitones to this note. For example, $62 represents up 2 semitones or a major second (bits 4-0: %00010 or +2) and 8 frames long (bits 7-5: %011 or 3, and 2^3 = 8). $9B would mean down 5 semitones or a perfect fourth (bits 4-0: %11011 or -5) and 16 frames long (bits 7-5: %100 or 4, and 2^4 = 16). Codes $E0-$FF have a separate meaning that I haven't bothered to crack, as I did not need it for this hack. The motif in Klax ----------------- This motif appears in two of the six pieces in the _Klax_ soundtrack by Bügsük (Lx Rudis and Dave O'Riva). E, E, F#, E, E, G, E, E G#, E, E, A, E, E, Bb, A Because of limits in pattern-sharing in the driver, there are several copies of this motif in this bank of the ROM. Two are in "Title" A9F9: 60 60 62 7E 60 63 7D 60 64 7C 60 65 7B 60 66 7F This starts out meaning `same same +M2 -M2 same +m3 -m3 same`, etc. A CPU read breakpoint at `AA01` triggers halfway through this motif. A second copy in "Title" starts with `6C 60...` where `6C` means "go up an octave" but is otherwise identical. The motif is repeated a few times throughout the music data of "Caverns of Cthulu" such as at `B17A`. One copy of the motif in "Caverns" at `B1BC` changes the intervals to move all of the lowest notes up an octave: 60 60 76 6A 60 77 69 60 78 68 60 79 67 60 7A 7F A CPU read breakpoint at B1C8 catches this one. Changing it to Doom ------------------- In Bobby Prince's soundtrack for _Doom_, the piece "At Doom's Gate" is heard in episode 1 mission 1 (E1M1) "Hangar". It employs a motif similar in shape and rhythm to the motif in _Klax_, but upside down. E, E, E', E, E, D', E, E C', E, E, A#, E, E, B, C To insert this motif into _Klax_, search for all instances of these bytes: 62 7E 60 63 7D 60 64 7C 60 65 7B 60 66 7F replacing them with these bytes: 6C 74 60 6A 76 60 68 78 60 66 7A 60 67 61 I left the one with the lowest notes up an octave as is because it moves in opposite directions anyway. The IPS patch ------------- Searching and replacing in a hex editor as described above is enough to get _Klax_ to sound like _Doom_. To make this easier, use [Lipx] or any other IPS patch software to apply "Klax (Doom's Gate).nes.ips" to your copy of _Klax_. $ crc32 "Klax (U).nes" 755cf043 Klax (U).nes $ md5sum "Klax (U).nes" f957b5d342a2106afc470577c3412588 Klax (U).nes $ sha1sum "Klax (U).nes" 80a2ea6e52b96506613912ff9a15657a29c9684a Klax (U).nes $ sha256sum "Klax (U).nes" d010708d6e4bfd208d9ce0a5ae55a6319700b05d87eabbebc1df5527781773e0 Klax (U).nes I also decided to change the title of "Caverns of Cthulu" in Options. This required figuring out a "table" for the character encoding used on that screen. It turned out that glyphs are in the same order as ASCII, with $80-$B9 in _Klax_ corresponding to $21-$5A in ASCII. Space is $BD. With "Klax (U).tbl" loaded into FCEUX's hex editor, I changed the title to `AT_DOOM'S_`/`GATE__`, filling unused parts of the string with spaces in order not to waste time on pointer hunting. [Lipx]: https://github.com/kylon/Lipx