~ubuntu-branches/ubuntu/trusty/rlvm/trusty

« back to all changes in this revision

Viewing changes to .pc/002_675426ad62bccf1de10b0ae31dd46331ec47aacb.patch/src/Systems/Base/KOEPACVoiceArchive.cpp

  • Committer: Package Import Robot
  • Author(s): Ying-Chun Liu (PaulLiu)
  • Date: 2013-11-02 02:57:13 UTC
  • mfrom: (10.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20131102025713-yzg31grxr8i7xerh
Tags: 0.13-1
* New upstream release
  - rlvm will now warn on startup when it detects Japanese save data, but
    English patched game files, and offer to reset the save data.
  - Much better support for Little Busters. Most graphical glitches during
    the Little Busters Refrain have been fixed.
  - TCC tone curve effects have been reverse-engineered and implemented
    (thanks to lurkmoar)
  - Sepia scenes (and other graphical filters) should look much better.
  - Simple shake commands implemented (fancy per-layer shaking still
    unimplemented).
  - Make animations smooth: data should be uploaded to the graphics card
    before an animation loop starts, not while the animation loop is
    running.
  - Fixes finding system fonts on Linux
  - Thanks to Elliot Glaysher <glaysher@umich.edu>
* Remove upstreamed patches:
  - debian/patches/002_675426ad62bccf1de10b0ae31dd46331ec47aacb.patch
  - debian/patches/003_5dafabf5448635c4d4526d6e35ea7ec664a27261.patch
  - debian/patches/004_boost-drop-mt.patch
  - debian/patches/005_missing-include.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2
 
// vi:tw=80:et:ts=2:sts=2
3
 
//
4
 
// -----------------------------------------------------------------------
5
 
//
6
 
// This file is part of RLVM, a RealLive virtual machine clone.
7
 
//
8
 
// -----------------------------------------------------------------------
9
 
//
10
 
// Copyright (C) 2009 Elliot Glaysher
11
 
//
12
 
// This program is free software; you can redistribute it and/or modify
13
 
// it under the terms of the GNU General Public License as published by
14
 
// the Free Software Foundation; either version 3 of the License, or
15
 
// (at your option) any later version.
16
 
//
17
 
// This program is distributed in the hope that it will be useful,
18
 
// but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 
// GNU General Public License for more details.
21
 
//
22
 
// You should have received a copy of the GNU General Public License
23
 
// along with this program; if not, write to the Free Software
24
 
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
25
 
//
26
 
// -----------------------------------------------------------------------
27
 
//
28
 
// Parts of this file have been copied from koedec.cc in the xclannad
29
 
// distribution and they are:
30
 
//
31
 
// Copyright (c) 2004-2006  Kazunori "jagarl" Ueno
32
 
// All rights reserved.
33
 
//
34
 
// Redistribution and use in source and binary forms, with or without
35
 
// modification, are permitted provided that the following conditions
36
 
// are met:
37
 
// 1. Redistributions of source code must retain the above copyright
38
 
//    notice, this list of conditions and the following disclaimer.
39
 
// 2. Redistributions in binary form must reproduce the above copyright
40
 
//    notice, this list of conditions and the following disclaimer in the
41
 
//    documentation and/or other materials provided with the distribution.
42
 
// 3. The name of the author may not be used to endorse or promote products
43
 
//    derived from this software without specific prior written permission.
44
 
//
45
 
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
46
 
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47
 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
48
 
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
49
 
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50
 
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
51
 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
52
 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53
 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
54
 
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55
 
//
56
 
// -----------------------------------------------------------------------
57
 
 
58
 
#include "Systems/Base/KOEPACVoiceArchive.hpp"
59
 
 
60
 
#include <algorithm>
61
 
#include <cstring>
62
 
#include <fstream>
63
 
#include <sstream>
64
 
#include <vector>
65
 
#include <boost/filesystem/path.hpp>
66
 
#include <boost/filesystem/fstream.hpp>
67
 
#include <boost/scoped_array.hpp>
68
 
 
69
 
#include "Utilities/Exception.hpp"
70
 
#include "xclannad/endian.hpp"
71
 
 
72
 
using namespace std;
73
 
using boost::scoped_array;
74
 
using boost::shared_ptr;
75
 
using std::ifstream;
76
 
using std::ostringstream;
77
 
namespace fs = boost::filesystem;
78
 
 
79
 
namespace {
80
 
 
81
 
// KOEPAC translation tables provided by Jagarl.
82
 
 
83
 
/* 8bit -> 16bit への変換テーブル。本来は signed short だが
84
 
** とりあえず unsigned で扱っている
85
 
*/
86
 
 
87
 
uint16_t koe_8bit_trans_tbl[256] = {
88
 
  0x8000, 0x81ff, 0x83f9, 0x85ef, 0x87e1, 0x89cf, 0x8bb9, 0x8d9f,
89
 
  0x8f81, 0x915f, 0x9339, 0x950f, 0x96e1, 0x98af, 0x9a79, 0x9c3f,
90
 
  0x9e01, 0x9fbf, 0xa179, 0xa32f, 0xa4e1, 0xa68f, 0xa839, 0xa9df,
91
 
  0xab81, 0xad1f, 0xaeb9, 0xb04f, 0xb1e1, 0xb36f, 0xb4f9, 0xb67f,
92
 
  0xb801, 0xb97f, 0xbaf9, 0xbc6f, 0xbde1, 0xbf4f, 0xc0b9, 0xc21f,
93
 
  0xc381, 0xc4df, 0xc639, 0xc78f, 0xc8e1, 0xca2f, 0xcb79, 0xccbf,
94
 
  0xce01, 0xcf3f, 0xd079, 0xd1af, 0xd2e1, 0xd40f, 0xd539, 0xd65f,
95
 
  0xd781, 0xd89f, 0xd9b9, 0xdacf, 0xdbe1, 0xdcef, 0xddf9, 0xdeff,
96
 
  0xe001, 0xe0ff, 0xe1f9, 0xe2ef, 0xe3e1, 0xe4cf, 0xe5b9, 0xe69f,
97
 
  0xe781, 0xe85f, 0xe939, 0xea0f, 0xeae1, 0xebaf, 0xec79, 0xed3f,
98
 
  0xee01, 0xeebf, 0xef79, 0xf02f, 0xf0e1, 0xf18f, 0xf239, 0xf2df,
99
 
  0xf381, 0xf41f, 0xf4b9, 0xf54f, 0xf5e1, 0xf66f, 0xf6f9, 0xf77f,
100
 
  0xf801, 0xf87f, 0xf8f9, 0xf96f, 0xf9e1, 0xfa4f, 0xfab9, 0xfb1f,
101
 
  0xfb81, 0xfbdf, 0xfc39, 0xfc8f, 0xfce1, 0xfd2f, 0xfd79, 0xfdbf,
102
 
  0xfe01, 0xfe3f, 0xfe79, 0xfeaf, 0xfee1, 0xff0f, 0xff39, 0xff5f,
103
 
  0xff81, 0xff9f, 0xffb9, 0xffcf, 0xffe1, 0xffef, 0xfff9, 0xffff,
104
 
  0x0000, 0x0001, 0x0007, 0x0011, 0x001f, 0x0031, 0x0047, 0x0061,
105
 
  0x007f, 0x00a1, 0x00c7, 0x00f1, 0x011f, 0x0151, 0x0187, 0x01c1,
106
 
  0x01ff, 0x0241, 0x0287, 0x02d1, 0x031f, 0x0371, 0x03c7, 0x0421,
107
 
  0x047f, 0x04e1, 0x0547, 0x05b1, 0x061f, 0x0691, 0x0707, 0x0781,
108
 
  0x07ff, 0x0881, 0x0907, 0x0991, 0x0a1f, 0x0ab1, 0x0b47, 0x0be1,
109
 
  0x0c7f, 0x0d21, 0x0dc7, 0x0e71, 0x0f1f, 0x0fd1, 0x1087, 0x1141,
110
 
  0x11ff, 0x12c1, 0x1387, 0x1451, 0x151f, 0x15f1, 0x16c7, 0x17a1,
111
 
  0x187f, 0x1961, 0x1a47, 0x1b31, 0x1c1f, 0x1d11, 0x1e07, 0x1f01,
112
 
  0x1fff, 0x2101, 0x2207, 0x2311, 0x241f, 0x2531, 0x2647, 0x2761,
113
 
  0x287f, 0x29a1, 0x2ac7, 0x2bf1, 0x2d1f, 0x2e51, 0x2f87, 0x30c1,
114
 
  0x31ff, 0x3341, 0x3487, 0x35d1, 0x371f, 0x3871, 0x39c7, 0x3b21,
115
 
  0x3c7f, 0x3de1, 0x3f47, 0x40b1, 0x421f, 0x4391, 0x4507, 0x4681,
116
 
  0x47ff, 0x4981, 0x4b07, 0x4c91, 0x4e1f, 0x4fb1, 0x5147, 0x52e1,
117
 
  0x547f, 0x5621, 0x57c7, 0x5971, 0x5b1f, 0x5cd1, 0x5e87, 0x6041,
118
 
  0x61ff, 0x63c1, 0x6587, 0x6751, 0x691f, 0x6af1, 0x6cc7, 0x6ea1,
119
 
  0x707f, 0x7261, 0x7447, 0x7631, 0x781f, 0x7a11, 0x7c07, 0x7fff
120
 
};
121
 
 
122
 
/* ADPCM・・・じゃないらしい。ただのDPCMのナめたテーブル。
123
 
** 自動生成すりゃいいんだけど256byteだったら
124
 
** テーブルでも問題ないでしょ
125
 
*/
126
 
 
127
 
int8_t koe_ad_trans_tbl[256] = {
128
 
  0x00, 0xff, 0x01, 0xfe, 0x02, 0xfd, 0x03, 0xfc,
129
 
  0x04, 0xfb, 0x05, 0xfa, 0x06, 0xf9, 0x07, 0xf8,
130
 
  0x08, 0xf7, 0x09, 0xf6, 0x0a, 0xf5, 0x0b, 0xf4,
131
 
  0x0c, 0xf3, 0x0d, 0xf2, 0x0e, 0xf1, 0x0f, 0xf0,
132
 
  0x10, 0xef, 0x11, 0xee, 0x12, 0xed, 0x13, 0xec,
133
 
  0x14, 0xeb, 0x15, 0xea, 0x16, 0xe9, 0x17, 0xe8,
134
 
  0x18, 0xe7, 0x19, 0xe6, 0x1a, 0xe5, 0x1b, 0xe4,
135
 
  0x1c, 0xe3, 0x1d, 0xe2, 0x1e, 0xe1, 0x1f, 0xe0,
136
 
  0x20, 0xdf, 0x21, 0xde, 0x22, 0xdd, 0x23, 0xdc,
137
 
  0x24, 0xdb, 0x25, 0xda, 0x26, 0xd9, 0x27, 0xd8,
138
 
  0x28, 0xd7, 0x29, 0xd6, 0x2a, 0xd5, 0x2b, 0xd4,
139
 
  0x2c, 0xd3, 0x2d, 0xd2, 0x2e, 0xd1, 0x2f, 0xd0,
140
 
  0x30, 0xcf, 0x31, 0xce, 0x32, 0xcd, 0x33, 0xcc,
141
 
  0x34, 0xcb, 0x35, 0xca, 0x36, 0xc9, 0x37, 0xc8,
142
 
  0x38, 0xc7, 0x39, 0xc6, 0x3a, 0xc5, 0x3b, 0xc4,
143
 
  0x3c, 0xc3, 0x3d, 0xc2, 0x3e, 0xc1, 0x3f, 0xc0,
144
 
  0x40, 0xbf, 0x41, 0xbe, 0x42, 0xbd, 0x43, 0xbc,
145
 
  0x44, 0xbb, 0x45, 0xba, 0x46, 0xb9, 0x47, 0xb8,
146
 
  0x48, 0xb7, 0x49, 0xb6, 0x4a, 0xb5, 0x4b, 0xb4,
147
 
  0x4c, 0xb3, 0x4d, 0xb2, 0x4e, 0xb1, 0x4f, 0xb0,
148
 
  0x50, 0xaf, 0x51, 0xae, 0x52, 0xad, 0x53, 0xac,
149
 
  0x54, 0xab, 0x55, 0xaa, 0x56, 0xa9, 0x57, 0xa8,
150
 
  0x58, 0xa7, 0x59, 0xa6, 0x5a, 0xa5, 0x5b, 0xa4,
151
 
  0x5c, 0xa3, 0x5d, 0xa2, 0x5e, 0xa1, 0x5f, 0xa0,
152
 
  0x60, 0x9f, 0x61, 0x9e, 0x62, 0x9d, 0x63, 0x9c,
153
 
  0x64, 0x9b, 0x65, 0x9a, 0x66, 0x99, 0x67, 0x98,
154
 
  0x68, 0x97, 0x69, 0x96, 0x6a, 0x95, 0x6b, 0x94,
155
 
  0x6c, 0x93, 0x6d, 0x92, 0x6e, 0x91, 0x6f, 0x90,
156
 
  0x70, 0x8f, 0x71, 0x8e, 0x72, 0x8d, 0x73, 0x8c,
157
 
  0x74, 0x8b, 0x75, 0x8a, 0x76, 0x89, 0x77, 0x88,
158
 
  0x78, 0x87, 0x79, 0x86, 0x7a, 0x85, 0x7b, 0x84,
159
 
  0x7c, 0x83, 0x7d, 0x82, 0x7e, 0x81, 0x7f, 0x80
160
 
};
161
 
 
162
 
}  // namespace
163
 
 
164
 
// -----------------------------------------------------------------------
165
 
// KOEPACVoiceSample
166
 
// -----------------------------------------------------------------------
167
 
class KOEPACVoiceSample : public VoiceSample {
168
 
 public:
169
 
  KOEPACVoiceSample(fs::path file, int offset, int length, int rate)
170
 
      : stream_(std::fopen(file.external_file_string().c_str(), "rb")),
171
 
        offset_(offset), length_(length), rate_(rate) {
172
 
  }
173
 
 
174
 
  ~KOEPACVoiceSample() {
175
 
    if (stream_)
176
 
      fclose(stream_);
177
 
  }
178
 
 
179
 
  virtual char* decode(int* size);
180
 
 
181
 
 private:
182
 
  FILE* stream_;
183
 
  int offset_;
184
 
  int length_;
185
 
  int rate_;
186
 
};
187
 
 
188
 
char* KOEPACVoiceSample::decode(int* dest_len) {
189
 
  // This function has been mildly adapted from decode_koe in xclannad. I have
190
 
  // modified types so that it works on 64-bit systems and changed malloc()s to
191
 
  // new[]s, as the consumer of decode() will delete [] the returned pointer.
192
 
 
193
 
  // avg32 の声データ展開
194
 
  scoped_array<char> table(new char[length_ * 2]);
195
 
  fseek(stream_, offset_, 0);
196
 
  fread(table.get(), 2, length_, stream_);
197
 
 
198
 
  int all_len = 0;
199
 
  for (int i = 0; i < length_; i++)
200
 
    all_len += read_little_endian_short(table.get() + i*2);
201
 
 
202
 
  // データ読み込み
203
 
  uint8_t* src_orig  = new uint8_t[all_len];
204
 
  uint16_t* dest_orig = new uint16_t[length_ * 0x1000 + 0x2c];
205
 
 
206
 
  if (src_orig == NULL || dest_orig == NULL) return NULL;
207
 
  uint8_t* src = src_orig;
208
 
  fread(src, 1, all_len, stream_);
209
 
  *dest_len = length_ * 0x400 * 4;
210
 
  const char* header = MakeWavHeader(rate_, 2, 2, *dest_len);
211
 
  memcpy(dest_orig, header, 0x2c);
212
 
  uint16_t* dest = dest_orig + 0x2c;
213
 
 
214
 
  // 展開
215
 
  for (int i = 0; i < length_; i++) {
216
 
    int slen = read_little_endian_short(table.get() + i * 2);
217
 
    if (slen == 0) {  // do nothing
218
 
      memset(dest, 0, 0x1000);
219
 
      dest += 0x800;
220
 
      src += 0;
221
 
    } else if (slen == 0x400) {  // table 変換
222
 
      for (int j = 0; j < 0x400; j++) {
223
 
        write_little_endian_short((char*)(dest+0), koe_8bit_trans_tbl[*src]);
224
 
        write_little_endian_short((char*)(dest+1), koe_8bit_trans_tbl[*src]);
225
 
        dest += 2;
226
 
        src++;
227
 
      }
228
 
    } else {  // DPCM
229
 
      int8_t d = 0;
230
 
      int16_t o2;
231
 
      for (int j = 0, k = 0; j < slen && k < 0x800; j++) {
232
 
        uint8_t s = src[j];
233
 
        if ((s+1) & 0x0f) {
234
 
          d -= koe_ad_trans_tbl[s & 0x0f];
235
 
        } else {
236
 
          uint8_t s2;
237
 
          s >>= 4;
238
 
          s &= 0x0f;
239
 
          s2 = s;
240
 
          s = src[++j];
241
 
          s2 |= (s<<4) & 0xf0;
242
 
          d -= koe_ad_trans_tbl[s2];
243
 
        }
244
 
        o2 = koe_8bit_trans_tbl[(uint8_t)d];
245
 
        write_little_endian_short((char*)(dest+k), o2);
246
 
        write_little_endian_short((char*)(dest+k+1), o2);
247
 
        k+=2;
248
 
        s >>= 4;
249
 
        if ((s+1) & 0x0f) {
250
 
          d -= koe_ad_trans_tbl[s & 0x0f];
251
 
        } else {
252
 
          d -= koe_ad_trans_tbl[ src[++j] ];
253
 
        }
254
 
        o2 = koe_8bit_trans_tbl[ (unsigned char)d];
255
 
        write_little_endian_short((char*)(dest+k), o2);
256
 
        write_little_endian_short((char*)(dest+k+1), o2);
257
 
        k+=2;
258
 
      }
259
 
      dest += 0x800;
260
 
      src += slen;
261
 
    }
262
 
  }
263
 
  delete [] src_orig;
264
 
 
265
 
  return (char*)dest_orig;
266
 
}
267
 
 
268
 
// -----------------------------------------------------------------------
269
 
// KOEPACVoiceArchive
270
 
// -----------------------------------------------------------------------
271
 
KOEPACVoiceArchive::KOEPACVoiceArchive(fs::path file, int file_no)
272
 
    : VoiceArchive(file_no),
273
 
      file_(file) {
274
 
  readTable(file);
275
 
}
276
 
 
277
 
// -----------------------------------------------------------------------
278
 
 
279
 
KOEPACVoiceArchive::~KOEPACVoiceArchive() {
280
 
}
281
 
 
282
 
// -----------------------------------------------------------------------
283
 
 
284
 
shared_ptr<VoiceSample> KOEPACVoiceArchive::findSample(int sample_num) {
285
 
  std::vector<Entry>::const_iterator it =
286
 
      std::lower_bound(entries_.begin(), entries_.end(), sample_num);
287
 
  if (it != entries_.end()) {
288
 
    return shared_ptr<VoiceSample>(
289
 
        new KOEPACVoiceSample(file_, it->offset, it->length, rate_));
290
 
  }
291
 
 
292
 
  throw rlvm::Exception("Couldn't find sample in KOEPACVoiceArchive");
293
 
}
294
 
 
295
 
// -----------------------------------------------------------------------
296
 
 
297
 
void KOEPACVoiceArchive::readTable(boost::filesystem::path file) {
298
 
  fs::ifstream ifs(file, ifstream::in | ifstream::binary);
299
 
  if (!ifs) {
300
 
    ostringstream oss;
301
 
    oss << "Could not open file \"" << file << "\".";
302
 
    throw rlvm::Exception(oss.str());
303
 
  }
304
 
 
305
 
  // Copied from koedec.cc
306
 
  char head[0x20];
307
 
  ifs.read(head, 0x20);
308
 
  if (strncmp(head, "KOEPAC", 7) != 0) {
309
 
    ostringstream oss;
310
 
    oss << file << " does not appear to be in KOEPAC format";
311
 
    throw rlvm::Exception(oss.str());
312
 
  }
313
 
 
314
 
  int table_len = read_little_endian_int(head + 0x10);
315
 
  entries_.reserve(table_len);
316
 
 
317
 
  rate_ = read_little_endian_int(head + 0x18);
318
 
  if (rate_ == 0) {
319
 
    rate_ = 22050;
320
 
  }
321
 
 
322
 
  char* buf = new char[table_len * 8];
323
 
  ifs.read(buf, table_len * 8);
324
 
  for (int i = 0; i < table_len; i++) {
325
 
    int koe_num = read_little_endian_short(buf + i * 8);
326
 
    int length  = read_little_endian_short(buf + i * 8 + 2);
327
 
    int offset = read_little_endian_int(buf + i * 8 + 4);
328
 
    entries_.push_back(Entry(koe_num, length, offset));
329
 
  }
330
 
  sort(entries_.begin(), entries_.end());
331
 
 
332
 
  delete [] buf;
333
 
}