-
Notifications
You must be signed in to change notification settings - Fork 2
/
Mrifk_objects.hs
101 lines (78 loc) · 2.95 KB
/
Mrifk_objects.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
{-
Mrifk, a decompiler for Glulx story files.
Copyright 2004 Ben Rudiak-Gould.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You can read the GNU General Public License at this URL:
http://www.gnu.org/copyleft/gpl.html
-}
module Mrifk_objects (
Object(..),
objects, numObjects, objectForest
) where
import Mrifk_strings
import Mrifk_storyfile
import Mrifk_memmap
import Mrifk_util
import Control.Monad (replicateM)
import Control.Monad.State (evalState)
import Data.Array
import Data.Bits (testBit)
import Data.Tree
import Data.Maybe (fromJust)
-- name attrs prop# priv data
data Object = Object String [Int] [(Int,Bool,[Int])]
type Object' = ((Int,Object),Int,Int,Int)
objectForest :: Forest Int
objectForest =
map treeFrom roots
where parents = makeLookupTable [(a,p) | ((a,_),p,_,_) <- objectList]
siblings = makeLookupTable [(a,s) | ((a,_),_,s,_) <- objectList]
children = makeLookupTable [(a,c) | ((a,_),_,_,c) <- objectList]
roots = [a | ((a,_),0,_,_) <- objectList]
treeFrom n =
let kids = takeWhile (/= 0) $
iterate (fromJust . flip tableLookup siblings)
(fromJust $ tableLookup n children)
in Node n (map treeFrom kids)
objects :: [(Int,Object)]
objects = [o | (o,_,_,_) <- objectList]
numObjects :: Int
numObjects = length objectList
objectList :: [Object']
objectList =
evalState (repeatUntilEmpty getObject) informObjectTable
getObject =
do addr <- getPos
typeByte <- getUByte -- we already verified this is 0x70 when searching for the object table
attribBytes <- replicateM numAttribBytes getUByte
nextAddr <- getDword
nameAddr <- getDword
propAddr <- getDword
parent <- getDword
sibling <- getDword
child <- getDword
let name = evalFrom nameAddr decodeString
attribs = decodeAttribsFrom 0 attribBytes
props = evalFrom propAddr getProps
return ((addr, Object name attribs props), parent, sibling, child)
decodeAttribsFrom n [] = []
decodeAttribsFrom n (b:bs) =
[n+i | i <- [0..7], testBit b i] ++ decodeAttribsFrom (n+8) bs
getProps =
do numProps <- getDword
replicateM numProps getProp
getProp =
do id <- getUWord
len <- getUWord
addr <- getDword
flags <- getUWord
let private = testBit flags 0
data_ = evalFrom addr (replicateM len getDword)
return (id,private,data_)