5 * Created by Alyssa Milburn on Tue 16 Nov 2004.
6 * Copyright (c) 2004-2006 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
20 #include "endianlove.h"
21 #include "exceptions.h"
30 mngFlexLexer
*mnglexer
= NULL
;
31 MNGFile
*g_mngfile
= NULL
;
32 extern int mngparse(); // parser
34 void decryptbuf(char * buf
, int len
) {
36 unsigned char pad
= 5;
37 for(i
= 0; i
< len
; i
++) {
43 MNGFile::MNGFile(std::string n
) {
48 f
= fopen(name
.c_str(), "r");
50 throw MNGFileException("Can't open file", errno
);
53 // Hack to obtain the filesize
54 fseek(f
, 0, SEEK_END
);
58 map
= (char *) mmap(0, filesize
, PROT_READ
, MAP_PRIVATE
, fileno(f
), 0);
59 if(map
== (void *) -1) {
60 throw MNGFileException("Can't mmap", errno
);
63 // Read metavariables from beginning of file
64 numsamples
= swapEndianLong(*((int *) map
));
65 scriptoffset
= swapEndianLong(*(((int *) map
) + 1));
66 scriptend
= swapEndianLong(*(((int *) map
) + 3));
67 scriptlength
= scriptend
- scriptoffset
;
70 for(int i
= 0; i
< numsamples
; i
++) {
71 // Sample offsets and lengths are stored in pairs after the initial 16 bytes
72 int position
= swapEndianLong(*((int *) map
+ 3 + (2 * i
)));
74 // skip four bytes of the WAVE header, four of the FMT header,
75 // the FMT chunk and four of the DATA header
76 position
+= swapEndianLong(*(int *)(map
+ position
)) + 8;
78 int size
= swapEndianLong(*((int *) (map
+ position
)));
79 position
+= 4; // Skip the size field
81 samples
.push_back(std::make_pair(map
+ position
, size
));
84 // now we have the samples, read and decode the MNG script
85 script
= (char *) malloc(scriptlength
+ 1);
86 script
[scriptlength
] = 0;
87 if(! script
) throw MNGFileException("malloc failed", errno
);
88 memcpy(script
, map
+ scriptoffset
, scriptlength
);
89 decryptbuf(script
, scriptlength
);
91 std::istringstream
tehscript(script
);
92 mngrestart(&tehscript
);
97 processState
*p
= new processState(this);
98 for (std::map
<std::string
, MNGEffectDecNode
*>::iterator i
= effects
.begin(); i
!= effects
.end(); i
++)
99 (*i
).second
->postProcess(p
);
100 for (std::map
<std::string
, MNGTrackDecNode
*>::iterator i
= tracks
.begin(); i
!= tracks
.end(); i
++)
101 (*i
).second
->postProcess(p
);
102 // don't call postProcess on variabledec!
106 void MNGFile::enumerateSamples() {
107 std::vector
< std::pair
< char *, int > >::iterator i
;
108 for(i
= samples
.begin(); i
!= samples
.end(); i
++) {
109 printf("Position: \"%p\" Length: %i\n", (void *)(*i
).first
, (*i
).second
);
110 // PlaySound((*i).second.first, (*i).second.second);
115 MNGFile::~MNGFile() {
117 munmap(map
, filesize
);
121 void mngrestart(std::istream
*is
) {
124 mnglexer
= new mngFlexLexer();
125 mnglexer
->yyrestart(is
);
128 void mngerror(char const *s
) {
129 throw creaturesException(s
);