„Az összevisszaságban találd meg az egyszerűséget, a hangzavarban a harmóniát...”

Hangok kinyerése az Impossible Missionből

Egy számomra komoly kihívást jelentő feladatról szeretnék írni, a napokban élesített projektem, az Impossible Mission kapcsán. Szokásomhoz híven, a játék minden nyersanyagát magam állítottam elő a játékból való kivagdosás módszerével. Emulátorban futtatva, képmentéseket és hangfelvételeket készítek, majd ezeket egységeire bontom. Így született meg például a sprite kép is. A hangok kinyerése is egyszerűnek tűnt, még falnak nem ütköztem...

Van két olyan hangeffekt a játékban, ami önmagában sohasem hallható, csak egy másik hang társaságában. A droidok megfordulásának hangja (amikor a platform széléhez érnek), illetve az elektromos nyaláb kilövésének hangja. Ez a kettő egészen biztosan csak akkor szól, ha a droidok alap morajlása is hallható. Mert ha az nem hallható, akkor vagy nincsenek is robotok a pályán, vagy le vannak bénítva, és így se nem fordulnak, se nem lőnek. Egy bútor képének kivágásához elég addig várnom, amíg elgurul előle az őt fedő robot, de itt a háttérhang sosem "gurul el". A feladat tehát az, hogy tisztán kinyerjem azt a hangot, amit nem hallok tisztán. A probléma megoldása felé rengeteg módon közelítettem, ezen esetlen próbálkozásaimat sorolom:

1. módszer: SID keresése a neten. És persze van is a játékhoz, viszont érthetően csak a fix hangokat tartalmazza. A számomra szükséges hangok viszont random generálódnak a játékban.

2. módszer: a hangmérnöki megközelítés. Adott két mono hangsáv, az egyikbe csak az alap morajlást vettem fel, a másikban ugyanaz az alap morajlás ÉS a kinyerni kívánt hang együtt. Magyarán van egy A és egy A+B hang, és nekem csak a B kellene tisztán. Ez elvileg megoldható úgy, ha az A-t invertálom, majd összemixelem az A+B-vel, mert így elvileg kioltja egymást az A és az invert A. Próbálkoztam is dögivel, de ehhez elképesztően pontos illesztés szükséges, csak akkor működik ha pont kioltják egymást a hullámok. Lehet hogy működne is a dolog, viszont rájöttem, hogy a háttér morajlás is random generálódik, és egy nagyon hosszú mintavétel után láttam, hogy bizony a számunkra monotonnak tűnő búgás mögött folyton változó hanghullám lapul! Így pedig lehetetlen a pontos egyeztetés. Persze biztosan vannak pro hangmérnökök akik megoldanák, de én nem vagyok az.

3. módszer: magam állítom elő a hangot. Vagyis addig buzerálom a SID-et, amíg azt a hangot nem préseli ki magából amit akarok. Nem hülyeség, de lássuk be, soha nem lett volna olyan, mint az eredeti. Ezen kívül túl macerásnak is tűnt.

4. módszer: az emulátor átconfigolása. Órákat töltöttem el azzal, hogy a létező összes C64 emulátort, SID szoftvert leszedtem és próbáltam configolni, hogy bizonyos hangsávokat elnémítsak a játék alatt. Kicsit hihetetlennek tűnik nekem, hogy jelen pillanatban egyik program sem képes erre. Milyen egyszerű is lett volna, lekapcsolom a morajlás sávját, és már kész is.

5. módszer: a programozó módszere. És nekem ez az ami bejött! Vagyis úgy döntöttem nem cicózok, átírom magát a játékot. Egyszerűen kikeresem a kódban azokat a részeket amik a zavaró hangot keltik, és kilövöm. Illetve annyira nem egyszerűen, számos dolog ismerete szükséges hozzá. Előkerült a polcról Molnár Lajos - Amit a C64-esről tudni érdemes című könnyed olvasmánya. Fellapoztam a SID regisztereit tárgyaló fejezetet. Megkopott emlékeimet rebootoltam, az 54272-es szám olyan ismerősen csengett, mint a születésnapom dátuma.

A SID három szólamot tud. Az ötlet az volt, hogy kikeressem a kódból azon részeket, amik ezen három szólam jellemzőinek mahinálásáért felelősek. Majd próbálgatással, az egyes szólamok elnémításával kiszűröm a számomra szükségeset. A kódban való turkáláshoz a VICE emulátor monitorozóját használtam. A vállalkozó kedvű kollégák akár velem együtt is elvégezhetik az alábbi lépéseket.

18-as karika
Innentől 18-as karika

Töltsük be a játékot, és indítsuk el. Az ALT+M-re jön elő a monitor. Keressünk rá azon részekre, ahol valószínűleg a számunkra szükséges regisztereket ($D404, $D40B, $D412) seteli. Ezen regiszterek határozzák meg az adott szólam hullámformáját (háromszög, fűrészfog, négyszög, zaj), illetve ezen regiszter 3. bitjének magasra állításával lehet elnémítani azt.

assembly hunth 0000 ffff 8d 04 d4

H, vagyis hunt (vadászni). Ez annyit tesz, hogy a teljes területet (0000-ffff) átfésüli a megadott értékek sorozata után. Ami esetünkben: 8d (ez az STA, vagyis az akkumulátor regiszter tartalmának eltárolásáért felelős utasítás), a 04 d4 pedig az általunk keresett cím, a $D404. Magyarán azon részeket keressük most a kódban, ahol az első szólam vezérlőregisztere változik. Ki is dob jó pár találatot, lásd kép.

assembly disassemblyEzután a disassembly (d) következik, ahol végignézzük a kódot, és megpróbáljuk kitalálni, hogy a kapott címek körül mi is történik. Én végigzongoráztam mindet, sorba megtaláltam a telefon hangjait, a lift hangokat, stb. Most ezeket átugorva, egyből a lényegi részre ugranék:

d 925f

A képen láthatjuk, hogy az imént megtalált 9261 címen valóban az STA utasítás szerepel, a tárolási cím pedig a SID első szólamának vezérlőregisztere. Közvetlenül előtte pedig az akkumulátorba töltődik be az az érték, amit az STA letárol. Az eredeti érték #$41 vagyis binárisan 1000001, ami a 0. és 6. bit magasra állítottságát, vagyis egy négyszög hullámformát jelez. Ha mi ezt átállítjuk úgy, hogy a már említett 3. bit magas, akkor kikapcsoljuk ezt a szólamot. Tegyük meg!

assembly disassembly újra> 925f a9 08

Vagyis a 925f címre kerül az LDA (a9) utasítás, 8, vagyis binárisan 1000 értékkel (3. bit magas). Ha ezt megtettük, beavatkozásunk sikerességét egy újabb disassembly-vel nyugtázhatjuk, lásd a képen a megváltozott értéket.

Ha az exit (x) utasítással visszalépünk a játékba, azt hallhatjuk, hogy nem halljuk a droidok alapzaját. És épp ez az amire szükségünk volt. Hisz így már fel tudjuk venni a számunkra szükséges hangokat külön!

Személyes sikeremet több, egymást követő, artikulálatlan üvöltés formájában adtam a világ, de főleg a szomszédok tudtára.

A két hang: