Difference between revisions of "Music"
GreenReaper (talk | contribs) (Create) |
GreenReaper (talk | contribs) (Add content.) |
||
Line 1: | Line 1: | ||
{{Inuse}} | {{Inuse}} | ||
==Introduction== | ==Introduction== | ||
− | '''Music''' in the [[Creatures]] series of games started out in [[Creatures 1]] as a variety of synthesized chimes, chords, bloops and other non-specific sounds. For [[Creatures 2]], a far more capable system was created. | + | '''Music''' in the [[Creatures]] series of games started out in [[Creatures 1]] as a variety of synthesized chimes, chords, bloops and other non-specific sounds. For [[Creatures 2]], a far more capable system was created, as outlined below. This information was gained by [[User:GreenReaper]] during a university project and should not be considered official - no details of the MNG format were ever released by [[Creatures Labs]], only a three-page article ([[http://web.archive.org/web/20020614201723/http://www.creatures.co.uk/library/science/lib_science_musicbehind1.htm The Music of Creatures]]) describing some features. |
+ | |||
+ | ==Outline== | ||
+ | Music is stored in 'Munge' files, with the extension ''MNG'' (at the time, the MNG extension was not in use - it was later appropriated as a replacement for PNG). The music is formed of separate samples in a partial WAV format combined with a script which is interpreted by the music engine. | ||
+ | ==File Structure== | ||
+ | <table cellspacing="0" width="559"> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> Position</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | |||
+ | <p> Length</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Description</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> Notes</p> | ||
+ | |||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> 0</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> 4</p> | ||
+ | |||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Number of samples</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> </p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | |||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> 4</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> 4</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | |||
+ | <p> Position of | ||
+ | script</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> Zero-based byte | ||
+ | position</p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | |||
+ | <p> 8</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> 4</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Length of script</p> | ||
+ | |||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> Length in bytes</p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> 12</p> | ||
+ | |||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> 4</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Position of first | ||
+ | sample</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | |||
+ | <p> Zero-based byte | ||
+ | position</p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> 16</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | |||
+ | <p> 4</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Length of first | ||
+ | sample</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> Length in bytes</p> | ||
+ | |||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> 20</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> 4</p> | ||
+ | |||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Position of | ||
+ | second sample</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> Zero-based byte | ||
+ | position</p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | |||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> …</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> …</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | |||
+ | <p> …</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> </p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | |||
+ | <p> N * 8 + 8</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> 4</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 142.65pt;" valign="top" width="190"> | ||
+ | <p> Position of last sample</p> | ||
+ | </td> | ||
+ | |||
+ | <td style="border-width: thin; border-style: dashed;width: 153pt;" valign="top" width="204"> | ||
+ | <p> N is the number | ||
+ | of samples</p> | ||
+ | </td> | ||
+ | </tr> | ||
+ | <tr> | ||
+ | <td style="border-width: thin; border-style: dashed;width: 68.3pt;" valign="top" width="91"> | ||
+ | <p> N * 8 + 12</p> | ||
+ | </td> | ||
+ | |||
+ | <td style="border-width: thin; border-style: dashed;width: 55.45pt;" valign="top" width="74"> | ||
+ | <p> Variable</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;" valign="top" width="190"> | ||
+ | <p> First sample</p> | ||
+ | </td> | ||
+ | <td style="border-width: thin; border-style: dashed;" valign="top" width="204"> | ||
+ | <p> Followed by the | ||
+ | rest of the samples</p> | ||
+ | </td> | ||
+ | |||
+ | </tr> | ||
+ | </table> | ||
+ | ==Script Encryption== | ||
+ | The music scripts of MNG files are saved in a 'scrambled' format, encrypted with an XOR function. This function works on a byte level, with a starting operand value of 0x5 and an increment of 0xC1. Sample routines follow - as XOR is a reversible operation, they can be used to both scramble and descramble scripts. | ||
+ | |||
+ | ===Visual Basic Routine=== | ||
+ | <pre> | ||
+ | Private Function Scramble(ByVal data As Byte()) As Byte() | ||
+ | Dim hb as Byte, count as Integer | ||
+ | hb = 5 | ||
+ | For count = 0 to data.Length – 1 | ||
+ | data(count) = data(count) Xor hb | ||
+ | If hb < &H3F Then | ||
+ | hb = CByte(hb + &HC1) | ||
+ | Else | ||
+ | hb = Cbyte(hb + (&HC1 - &H100)) | ||
+ | End If | ||
+ | Next count | ||
+ | Return data | ||
+ | End Function | ||
+ | </pre> | ||
+ | |||
+ | ===Assembly Routine=== | ||
+ | <pre> | ||
+ | .text:00543400 sub_0_543400 proc near .text:00543400 | ||
+ | .text:00543400 arg_0 = dword ptr 8 | ||
+ | .text:00543400 arg_4 = dword ptr 0Ch | ||
+ | .text:00543400 | ||
+ | .text:00543400 push ebp | ||
+ | .text:00543401 mov ebp, esp | ||
+ | .text:00543403 push esi | ||
+ | .text:00543404 mov esi, [ebp+arg_4] | ||
+ | .text:00543407 xor eax, eax | ||
+ | .text:00543409 mov cl, 5 | ||
+ | .text:0054340B test esi, esi | ||
+ | .text:0054340D jle short loc_0_543424 | ||
+ | .text:0054340F mov edx, [ebp+arg_0] | ||
+ | .text:00543412 push ebx | ||
+ | .text:00543413 | ||
+ | .text:00543413 loc_0_543413: ; CODE XREF: sub_0_543400+21 | ||
+ | .text:00543413 mov bl, [eax+edx] | ||
+ | .text:00543416 xor bl, cl | ||
+ | .text:00543418 add cl, 0C1h | ||
+ | .text:0054341B mov [eax+edx], bl | ||
+ | .text:0054341E inc eax | ||
+ | .text:0054341F cmp eax, esi | ||
+ | .text:00543421 jl short loc_0_543413 | ||
+ | .text:00543423 pop ebx | ||
+ | .text:00543424 | ||
+ | .text:00543424 loc_0_543424: ; CODE XREF: sub_0_543400+D | ||
+ | .text:00543424 pop esi | ||
+ | .text:00543425 pop ebp | ||
+ | .text:00543426 retn | ||
+ | .text:00543426 sub_0_543400 endp | ||
+ | </pre> |
Revision as of 02:23, 31 December 2004
Contents
Introduction
Music in the Creatures series of games started out in Creatures 1 as a variety of synthesized chimes, chords, bloops and other non-specific sounds. For Creatures 2, a far more capable system was created, as outlined below. This information was gained by User:GreenReaper during a university project and should not be considered official - no details of the MNG format were ever released by Creatures Labs, only a three-page article ([The Music of Creatures]) describing some features.
Outline
Music is stored in 'Munge' files, with the extension MNG (at the time, the MNG extension was not in use - it was later appropriated as a replacement for PNG). The music is formed of separate samples in a partial WAV format combined with a script which is interpreted by the music engine.
File Structure
Position |
Length |
Description |
Notes |
0 |
4 |
Number of samples |
|
4 |
4 |
Position of script |
Zero-based byte position |
8 |
4 |
Length of script |
Length in bytes |
12 |
4 |
Position of first sample |
Zero-based byte position |
16 |
4 |
Length of first sample |
Length in bytes |
20 |
4 |
Position of second sample |
Zero-based byte position |
… |
… |
… |
|
N * 8 + 8 |
4 |
Position of last sample |
N is the number of samples |
N * 8 + 12 |
Variable |
First sample |
Followed by the rest of the samples |
Script Encryption
The music scripts of MNG files are saved in a 'scrambled' format, encrypted with an XOR function. This function works on a byte level, with a starting operand value of 0x5 and an increment of 0xC1. Sample routines follow - as XOR is a reversible operation, they can be used to both scramble and descramble scripts.
Visual Basic Routine
Private Function Scramble(ByVal data As Byte()) As Byte() Dim hb as Byte, count as Integer hb = 5 For count = 0 to data.Length – 1 data(count) = data(count) Xor hb If hb < &H3F Then hb = CByte(hb + &HC1) Else hb = Cbyte(hb + (&HC1 - &H100)) End If Next count Return data End Function
Assembly Routine
.text:00543400 sub_0_543400 proc near .text:00543400 .text:00543400 arg_0 = dword ptr 8 .text:00543400 arg_4 = dword ptr 0Ch .text:00543400 .text:00543400 push ebp .text:00543401 mov ebp, esp .text:00543403 push esi .text:00543404 mov esi, [ebp+arg_4] .text:00543407 xor eax, eax .text:00543409 mov cl, 5 .text:0054340B test esi, esi .text:0054340D jle short loc_0_543424 .text:0054340F mov edx, [ebp+arg_0] .text:00543412 push ebx .text:00543413 .text:00543413 loc_0_543413: ; CODE XREF: sub_0_543400+21 .text:00543413 mov bl, [eax+edx] .text:00543416 xor bl, cl .text:00543418 add cl, 0C1h .text:0054341B mov [eax+edx], bl .text:0054341E inc eax .text:0054341F cmp eax, esi .text:00543421 jl short loc_0_543413 .text:00543423 pop ebx .text:00543424 .text:00543424 loc_0_543424: ; CODE XREF: sub_0_543400+D .text:00543424 pop esi .text:00543425 pop ebp .text:00543426 retn .text:00543426 sub_0_543400 endp