add hacky implementation of C1 speech/thought bubbles, unfinished
[openc2e.git] / mngfile.cpp
blob066ebc146d78340a75889a0ca8200e265d10aa96
1 /*
2 * mngfile.cpp
3 * openc2e
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.
19 #include <assert.h>
20 #include "endianlove.h"
21 #include "exceptions.h"
22 #include <stdio.h>
23 #include "mngfile.h"
24 #include <sys/mman.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include "lex.mng.h"
30 mngFlexLexer *mnglexer = NULL;
31 MNGFile *g_mngfile = NULL;
32 extern int mngparse(); // parser
34 void decryptbuf(char * buf, int len) {
35 int i;
36 unsigned char pad = 5;
37 for(i = 0; i < len; i++) {
38 buf[i] ^= pad;
39 pad += 0xC1;
43 MNGFile::MNGFile(std::string n) {
44 sampleno = 0;
46 name = n;
48 f = fopen(name.c_str(), "r");
49 if(!f) {
50 throw MNGFileException("Can't open file", errno);
53 // Hack to obtain the filesize
54 fseek(f, 0, SEEK_END);
55 filesize = ftell(f);
57 // mmap the data file
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;
69 // read the samples
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);
93 g_mngfile = this;
94 mngparse();
95 g_mngfile = 0;
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!
103 delete p;
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() {
116 free(script);
117 munmap(map, filesize);
118 fclose(f);
121 void mngrestart(std::istream *is) {
122 if (mnglexer)
123 delete mnglexer;
124 mnglexer = new mngFlexLexer();
125 mnglexer->yyrestart(is);
128 void mngerror(char const *s) {
129 throw creaturesException(s);
132 /* vim: set noet: */