General Category > Entertainment and Media

Unravelling the Secrets of "Normality" (1996)

(1/24) > >>

denzquix:


I am working out how to rip resources from the game files for the 3D point and click adventure game Normality by Gremlin Entertainment. I strongly suspect there to be many inaccessible/unused/secret things here. I want to look at them.


I will be updating this thread with my progress. I have not got very far yet, many of the files are encoded with a proprietary kind of compression. I will include decompression code once I have reverse engineered it, then I can start working out what's in the raw data


I believe this to be the first project of its kind anywhere on the web... the secrets of Normality will be spilled here, for the first time, live


Also: Analysis of the underlying politics, ideology and intentions of the Normality authors very welcome in this thread
 
 
 
 

dada:
Wowwww
Normality is one of my favorite games ever. I must have played through it about a dozen times. And yeah, there's something MYSTERIOUS about certain things. Like the park at the beginning of the game that you show. I've never been able to get in the normal way, but a while back I recorded some videos that show what happen if you do get in(by modifying the player's coordinates with a debugger).

Normality inaccessible area: the TV station set
http://www.youtube.com/watch?v=hP_QNRw5UmY

Normality inaccessible area: Saul's cell
http://www.youtube.com/watch?v=KclwqUUg8RM

Normality inaccessible area: the Plush-Rest furniture machine
http://www.youtube.com/watch?v=eKe-3YjnWiY

Normality inaccessible area: the park
http://www.youtube.com/watch?v=82TCgjop_jY

If you could find some way to rip the graphics, that would be awesome. I've always sort of had it in the back of my mind to try this but given that it's COMPLEX STUFF that I have no experience with, I've never given it a try.

dada:

--- Quote ---Also: Analysis of the underlying politics, ideology and intentions of the Normality authors very welcome in this thread
--- End quote ---
Check out the comments by BL1TZEN on this vid

http://www.youtube.com/watch?feature=player_embedded&v=MB_bACKgt9Y

Vellfire:
I was gonna freak out and alert dada about this topic but he already found it and now I feel foolish for thinking that a topic about Normality could show up on this forum and him not be in it IMMEDIATELY.

denzquix:


h'okay, I think I have cracked the decompression algorithm!!

the rest of this post will only be of interest to hardcore bytehackers who want to follow in my filthy footsteps


so, this compression scheme applies to any files that have the extension .MGL and this is some (Lua-ish) pseudocode code to decompress it
--- Code: ---repeat
  local b = read_byte()
  if (b == 0) or (b == nil) then
    -- zero byte marks the end of the stream
    break
  elseif b >= 0xE0 then
    local b2 = read_byte()
    local b3 = read_byte()
    local offset = ((b - 0xE0) * 256) + b2 + 3
    local length = b3 + 5
    reuse_bytes(offset, length)
  elseif b >= 0xC0 then
    local b2 = read_byte()
    local offset = ((b % 4) * 256) + b2 + 3
    local length = 4 + math.floor((b - 0xC0) / 4)
    reuse_bytes(offset, length)
  elseif b >= 0x80 then
    local offset = (b - 0x80) + 3
    reuse_bytes(offset, 3)
  elseif b >= 0x70 then
    local reps = (b - 0x70) + 2
    reuse_bytes(2, 2, reps)
  elseif b >= 0x60 then
    local reps = (b - 0x60) + 3
    reuse_bytes(1, 1, reps)
  elseif b >= 0x50 then
    local length = (b - 0x50) + 2
    uint16LE_pattern_sequence(length)
  elseif b >= 0x40 then
    local length = (b - 0x40) + 3
    byte_pattern_sequence(length)
  else
    local length = b
    copy_input_bytes(length)
  end
until (b == 0) or (b == nil)
--- End code ---
this is the core loop, it requires the following functions be defined first:
* read_byte(): Read 1 byte from the input stream, and return its value as a number. If the end of the stream is reached, return nil.
* copy_input_bytes(length): Take a chunk of bytes from the input stream, and write it direct to the output stream.
* reuse_bytes(offset, length[, repeats]): Take a chunk of bytes that have previously been written to the output stream, and re-append it to the end. The chunk begins offset bytes backwards from the end of the stream. If length is greater than offset, repeat the chunk like a pattern - for example if reuse_bytes(5, 9) is called and the last five bytes written spell "Hello" in ASCII, "HelloHell" should be written to the output stream. If the optional parameter repeats is given, repeat the chunk that number of times.
* byte_pattern_sequence(length): Use the last two bytes written to the output stream to continue with a pattern. For example if the last two byte values were 02 03, the sequence would continue 04 05 06 07...
* uint16LE_pattern_sequence(length): Same as byte_pattern_sequence() but with 16-bit short integers (Little-Endian encoded) instead of bytes. So note the total number of bytes written will be twice the value of length

Navigation

[0] Message Index

[#] Next page

Go to full version