Commits

Sylvain Rouquette committed 4a521cb

moved inc in src
renamed directories
removed platform, etc...

  • Participants
  • Parent commits 456d371
  • Branches input

Comments (0)

Files changed (174)

File game/assets/build.bat

+python ../waf build %*

File game/assets/clean.bat

+python ../waf clean %*

File game/assets/common/fonts/DroidSans.ttf

Binary file added.

File game/assets/common/fonts/DroidSansJapanese.ttf

Binary file added.

File game/assets/common/fonts/DroidSansMono.ttf

Binary file added.

File game/assets/common/fonts/charsets.py

+# encoding: utf-8
+
+katakana = u'''
+ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデト
+ドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰ
+ヱヲンヴヵヶヷヸヹヺ・ーヽヾ
+'''
+bopomofo = u'''
+ㄅㄆㄇㄈㄉㄊㄋㄌㄍㄎㄏㄐㄑㄒㄓㄔㄕㄖㄗㄘㄙㄚㄛㄜㄝㄞㄟㄠㄡㄢㄣㄤㄥㄦㄧㄨㄩㄪㄫㄬ
+ㄭㄮ
+'''
+latin_basic = u'''
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH
+IJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+qrstuvwxyz{|}~
+'''
+hiragana = u'''
+ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでと
+どなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろゎわゐ
+ゑをん
+'''
+latin_extended_b = u'''
+ƀƁƂƃƄƅƆƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧ
+ƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀǁǂǃDŽDždžLJLjljNJNjnjǍǎǏ
+ǐǑǒǓǔǕǖǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷ
+ǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟ
+ȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇ
+ɈɉɊɋɌɍɎ
+'''
+latin_extended_a = u'''
+ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħ
+ĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏ
+ŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷ
+ŸŹźŻżŽž
+'''

File game/assets/common/fonts/wscript

+#! /usr/bin/env python
+# encoding: utf-8
+
+import freetype as ft
+import numpy as np
+from os import path
+from waflib import Logs
+from tools.formats import font
+from tools import utils
+import charsets as cs
+
+
+def _bits(x):
+    data = []
+    for i in range(8):
+        data.insert(0, int((x & 1) == 1) * 255)
+        x = x >> 1
+    return data
+
+
+def _get_rasterized_glyph(bitmap, antialias):
+    w, h, p = bitmap.width, bitmap.rows, bitmap.pitch
+    data = []
+
+    if antialias:
+        data = bitmap.buffer
+    else:
+        for i in range(h):
+            row = []
+            for j in range(p):
+                row.extend(_bits(bitmap.buffer[i * p + j]))
+            data.extend(row[:w])
+
+    return w, h, data
+
+
+def build_font(ttf, size, charsets, image_size, antialias=True):
+    face = ft.Face(ttf)
+    face.set_char_size(size * 64)
+    texW, texH = image_size[0], image_size[1]
+    tex = np.zeros((texH, texW), dtype=np.ubyte)
+
+    if antialias:
+        ft_load_options = ft.FT_LOAD_RENDER
+    else:
+        ft_load_options = ft.FT_LOAD_RENDER | ft.FT_LOAD_TARGET_MONO
+
+    face.select_charmap(ft.FT_ENCODING_UNICODE)
+    class_font = font.create_font()
+
+    glyphs = []
+    error = False
+    x, y, margin = 0, 0, 1
+    for charset in charsets:
+        for c in charset:
+            if ((y + size + margin) > texH):
+                error = True
+                break
+            if c in ['\n', '\r']:
+                continue
+            face.load_char(c, ft_load_options)
+            glyph = face.glyph
+            w, h, data = _get_rasterized_glyph(glyph.bitmap, antialias)
+            if ((x + w + margin) > texW):
+                y += size + margin
+                x = 0
+
+            tex[y:y + h, x:x + w] |= np.array(data).reshape(h, w)
+            co_origin = (float(x) / float(texW), float(y) / float(texH))
+            co_size = (float(w) / float(texW), float(h) / float(texH))
+            advance = float(glyph.advance.x) / float(texW)
+            bearing = (glyph.bitmap_left / float(texW),
+                -glyph.bitmap_top / float(texH))
+            x += w + margin
+            glyphs.append(_create_glyph(
+                ord(c), co_origin, co_size, advance, bearing))
+    return tex, glyphs, error
+
+
+def _create_vector(vec):
+    class_vector = font.create_vector()
+    vector = class_vector.build()
+    vector['x'] = vec[0]
+    vector['y'] = vec[1]
+    return vector
+
+
+def _create_coords(origin, size):
+    class_coords = font.create_coords()
+    coords = class_coords.build()
+    coords['origin'] = _create_vector(origin)
+    coords['size'] = _create_vector(size)
+    return coords
+
+
+def _create_glyph(code, origin, size, advance, bearing):
+    class_glyph = font.create_glyph()
+    glyph = class_glyph.build()
+    glyph['code'] = code
+    glyph['coords'] = _create_coords(origin, size)
+    glyph['bearing'] = _create_vector(bearing)
+    glyph['advance'] = advance
+    return glyph
+
+
+def _create_font(data):
+    class_font = font.create_font()
+
+
+def _write_png(task, tex, gamma, filename):
+    import Image
+    tex = tex / 255.0
+    tex = tex ** (gamma)
+    tex = ((tex) * 255).astype(np.ubyte)
+    im = Image.fromarray(tex, mode='L')
+    im.save(filename)
+
+
+font_infos = {
+    'DroidSansMono.ttf': [
+        {'name': 'system', 'size': 11, 'image_size': (256, 256),
+            'antialias': False,
+            'charset': [cs.latin_basic],
+        },
+    ],
+    'DroidSans.ttf': [
+        {'name': 'font_latin', 'size': 16, 'image_size': (256, 256),
+            'antialias': True,
+            'charset': [cs.latin_basic,
+                cs.latin_extended_a, cs.latin_extended_b],
+        },
+    ],
+    'DroidSansJapanese.ttf': [
+        {'name': 'font_jp', 'size': 16, 'image_size': (256, 512),
+            'antialias': True,
+            'charset': [cs.hiragana, cs.katakana],
+        },
+    ],
+}
+
+
+def run(task):
+    if task.inputs[0].name not in font_infos:
+        return
+    class_font = font.create_font()
+    for font_info in font_infos[task.inputs[0].name]:
+        bitmap_font = class_font.build()
+        bitmap_font['base_scale'] = _create_vector(font_info['image_size'])
+        tex, glyphs, error = build_font(task.inputs[0].srcpath(),
+            font_info['size'], font_info['charset'],
+            font_info['image_size'], font_info['antialias'])
+        bitmap_font['glyphs'] = glyphs
+
+        if error:
+            fmt = 'Target image size too small for %s.png using %s.'
+            Logs.error(fmt % (font_info['name'], task.inputs[0].srcpath()))
+
+        output = task.generator.path.find_or_declare('%s.ttf.png' %
+            (font_info['name']))
+        if output not in task.outputs:
+            task.outputs.append(output)
+        _write_png(task, tex, 0.75, output.abspath())
+        font_dir = path.dirname(task.inputs[0].srcpath())
+        bitmap_font['texture'] = '%s/%s' % (font_dir, output.name)
+
+        output = task.generator.path.find_or_declare('%s.ttf.bmf' %
+            (font_info['name']))
+        if output not in task.outputs:
+            task.outputs.append(output)
+        with open(output.abspath(), 'w+b') as f:
+            class_font.write(f, bitmap_font, f.tell())
+
+
+def build(bld):
+    bld.declare_chain(
+        name='fonts',
+        rule=run,
+        color='CYAN',
+        ext_in='.ttf',
+        reentrant=False,
+    )
+    bld(source=bld.path.ant_glob('**/*.ttf'))
+
+    bld.add_group()
+    bld.declare_chain(
+        name='compress_fonts',
+        rule=utils.compress,
+        color='BLUE',
+        ext_in='.bmf',
+        ext_out='.bmfz',
+        reentrant=False,
+    )
+    bld(dynamic_source='**/*.bmf')
+    bld.add_group()
+    bld(dynamic_source='*.png')

File game/assets/common/geometries/object.dae

+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+  <asset>
+    <contributor>
+      <author>Blender User</author>
+      <authoring_tool>Blender 2.56.0 r34074</authoring_tool>
+    </contributor>
+    <created>2011-02-11T16:48:20</created>
+    <modified>2011-02-11T16:48:20</modified>
+    <unit name="meter" meter="1"/>
+    <up_axis>Z_UP</up_axis>
+  </asset>
+  <library_cameras>
+    <camera id="Camera_001-camera" name="Camera.001">
+      <optics>
+        <technique_common>
+          <perspective>
+            <xfov>49.13434</xfov>
+            <aspect_ratio>1.777778</aspect_ratio>
+            <znear>0.1</znear>
+            <zfar>100</zfar>
+          </perspective>
+        </technique_common>
+      </optics>
+    </camera>
+    <camera id="Camera-camera" name="Camera">
+      <optics>
+        <technique_common>
+          <perspective>
+            <xfov>49.13434</xfov>
+            <aspect_ratio>1.777778</aspect_ratio>
+            <znear>0.1</znear>
+            <zfar>100</zfar>
+          </perspective>
+        </technique_common>
+      </optics>
+    </camera>
+  </library_cameras>
+  <library_lights>
+    <light id="Lamp_001-light" name="Lamp.001">
+      <technique_common>
+        <point>
+          <color>1 1 1</color>
+          <constant_attenuation>1</constant_attenuation>
+          <linear_attenuation>0</linear_attenuation>
+          <quadratic_attenuation>5.55556e-4</quadratic_attenuation>
+        </point>
+      </technique_common>
+    </light>
+    <light id="Lamp-light" name="Lamp">
+      <technique_common>
+        <point>
+          <color>1 1 1</color>
+          <constant_attenuation>1</constant_attenuation>
+          <linear_attenuation>0</linear_attenuation>
+          <quadratic_attenuation>5.55556e-4</quadratic_attenuation>
+        </point>
+      </technique_common>
+    </light>
+  </library_lights>
+  <library_images>
+    <image id="m00_obj_omake1_png" name="m00_obj_omake1_png">
+      <init_from>m00_obj_omake1.png</init_from>
+    </image>
+  </library_images>
+  <library_effects>
+    <effect id="crate-effect">
+      <profile_COMMON>
+        <newparam sid="m00_obj_omake1_png-surface">
+          <surface type="2D">
+            <init_from>m00_obj_omake1_png</init_from>
+          </surface>
+        </newparam>
+        <newparam sid="m00_obj_omake1_png-sampler">
+          <sampler2D>
+            <source>m00_obj_omake1_png-surface</source>
+          </sampler2D>
+        </newparam>
+        <technique sid="common">
+          <lambert>
+            <emission>
+              <color>0 0 0 1</color>
+            </emission>
+            <ambient>
+              <color>0 0 0 1</color>
+            </ambient>
+            <diffuse>
+              <texture texture="m00_obj_omake1_png-sampler" texcoord="UVTex"/>
+            </diffuse>
+            <index_of_refraction>
+              <float>1</float>
+            </index_of_refraction>
+          </lambert>
+        </technique>
+        <extra>
+          <technique profile="GOOGLEEARTH">
+            <show_double_sided>1</show_double_sided>
+          </technique>
+        </extra>
+      </profile_COMMON>
+      <extra><technique profile="MAX3D"><double_sided>1</double_sided></technique></extra>
+    </effect>
+  </library_effects>
+  <library_materials>
+    <material id="crate" name="crate">
+      <instance_effect url="#crate-effect"/>
+    </material>
+  </library_materials>
+  <library_geometries>
+    <geometry id="Cube-mesh">
+      <mesh>
+        <source id="Cube-mesh-positions">
+          <float_array id="Cube-mesh-positions-array" count="24">1 1 -1 1 -1 -1 -1 -0.9999998 -1 -0.9999997 1 -1 1 0.9999995 1 0.9999994 -1.000001 1 -1 -0.9999997 1 -1 1 1</float_array>
+          <technique_common>
+            <accessor source="#Cube-mesh-positions-array" count="8" stride="3">
+              <param name="X" type="float"/>
+              <param name="Y" type="float"/>
+              <param name="Z" type="float"/>
+            </accessor>
+          </technique_common>
+        </source>
+        <source id="Cube-mesh-normals">
+          <float_array id="Cube-mesh-normals-array" count="18">0 0 -1 0 0 1 1 -1.49012e-7 1.49012e-7 -3.57628e-7 -1 -2.08616e-7 -1 0 0 1.19209e-7 1 1.19209e-7</float_array>
+          <technique_common>
+            <accessor source="#Cube-mesh-normals-array" count="6" stride="3">
+              <param name="X" type="float"/>
+              <param name="Y" type="float"/>
+              <param name="Z" type="float"/>
+            </accessor>
+          </technique_common>
+        </source>
+        <source id="Cube-mesh-map-0">
+          <float_array id="Cube-mesh-map-0-array" count="48">0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1</float_array>
+          <technique_common>
+            <accessor source="#Cube-mesh-map-0-array" count="24" stride="2">
+              <param name="S" type="float"/>
+              <param name="T" type="float"/>
+            </accessor>
+          </technique_common>
+        </source>
+        <vertices id="Cube-mesh-vertices">
+          <input semantic="POSITION" source="#Cube-mesh-positions"/>
+        </vertices>
+        <polylist material="crate" count="6">
+          <input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
+          <input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
+          <input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="0"/>
+          <vcount>4 4 4 4 4 4 </vcount>
+          <p>0 0 0 1 0 1 2 0 2 3 0 3 4 1 4 7 1 5 6 1 6 5 1 7 0 2 8 4 2 9 5 2 10 1 2 11 1 3 12 5 3 13 6 3 14 2 3 15 2 4 16 6 4 17 7 4 18 3 4 19 4 5 20 0 5 21 3 5 22 7 5 23</p>
+        </polylist>
+      </mesh>
+    </geometry>
+  </library_geometries>
+  <library_animations>
+    <animation id="Cube_location_X">
+      <source id="Cube_location_X-input">
+        <float_array id="Cube_location_X-input-array" count="3">0.04166656 2.125 4.208333</float_array>
+        <technique_common>
+          <accessor source="#Cube_location_X-input-array" count="3" stride="1">
+            <param name="TIME" type="float"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <source id="Cube_location_X-output">
+        <float_array id="Cube_location_X-output-array" count="3">0 -0.6732897 -0.5740851</float_array>
+        <technique_common>
+          <accessor source="#Cube_location_X-output-array" count="3" stride="1">
+            <param name="X" type="float"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <source id="Cube_location_X-interpolation">
+        <Name_array id="Cube_location_X-interpolation-array" count="3">LINEAR LINEAR LINEAR</Name_array>
+        <technique_common>
+          <accessor source="#Cube_location_X-interpolation-array" count="3" stride="1">
+            <param name="INTERPOLATION" type="name"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <sampler id="Cube_location_X-sampler">
+        <input semantic="INPUT" source="#Cube_location_X-input"/>
+        <input semantic="OUTPUT" source="#Cube_location_X-output"/>
+        <input semantic="INTERPOLATION" source="#Cube_location_X-interpolation"/>
+      </sampler>
+      <channel source="#Cube_location_X-sampler" target="Cube/location.X"/>
+    </animation>
+    <animation id="Cube_location_Y">
+      <source id="Cube_location_Y-input">
+        <float_array id="Cube_location_Y-input-array" count="3">0.04166656 2.125 4.208333</float_array>
+        <technique_common>
+          <accessor source="#Cube_location_Y-input-array" count="3" stride="1">
+            <param name="TIME" type="float"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <source id="Cube_location_Y-output">
+        <float_array id="Cube_location_Y-output-array" count="3">0 4.126082 -4.319929</float_array>
+        <technique_common>
+          <accessor source="#Cube_location_Y-output-array" count="3" stride="1">
+            <param name="Y" type="float"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <source id="Cube_location_Y-interpolation">
+        <Name_array id="Cube_location_Y-interpolation-array" count="3">LINEAR LINEAR LINEAR</Name_array>
+        <technique_common>
+          <accessor source="#Cube_location_Y-interpolation-array" count="3" stride="1">
+            <param name="INTERPOLATION" type="name"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <sampler id="Cube_location_Y-sampler">
+        <input semantic="INPUT" source="#Cube_location_Y-input"/>
+        <input semantic="OUTPUT" source="#Cube_location_Y-output"/>
+        <input semantic="INTERPOLATION" source="#Cube_location_Y-interpolation"/>
+      </sampler>
+      <channel source="#Cube_location_Y-sampler" target="Cube/location.Y"/>
+    </animation>
+    <animation id="Cube_location_Z">
+      <source id="Cube_location_Z-input">
+        <float_array id="Cube_location_Z-input-array" count="3">0.04166656 2.125 4.208333</float_array>
+        <technique_common>
+          <accessor source="#Cube_location_Z-input-array" count="3" stride="1">
+            <param name="TIME" type="float"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <source id="Cube_location_Z-output">
+        <float_array id="Cube_location_Z-output-array" count="3">0 4.58427 -2.450306</float_array>
+        <technique_common>
+          <accessor source="#Cube_location_Z-output-array" count="3" stride="1">
+            <param name="Z" type="float"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <source id="Cube_location_Z-interpolation">
+        <Name_array id="Cube_location_Z-interpolation-array" count="3">LINEAR LINEAR LINEAR</Name_array>
+        <technique_common>
+          <accessor source="#Cube_location_Z-interpolation-array" count="3" stride="1">
+            <param name="INTERPOLATION" type="name"/>
+          </accessor>
+        </technique_common>
+      </source>
+      <sampler id="Cube_location_Z-sampler">
+        <input semantic="INPUT" source="#Cube_location_Z-input"/>
+        <input semantic="OUTPUT" source="#Cube_location_Z-output"/>
+        <input semantic="INTERPOLATION" source="#Cube_location_Z-interpolation"/>
+      </sampler>
+      <channel source="#Cube_location_Z-sampler" target="Cube/location.Z"/>
+    </animation>
+  </library_animations>
+  <library_controllers/>
+  <library_visual_scenes>
+    <visual_scene id="Scene" name="Scene">
+      <node id="Camera_001" type="NODE">
+        <translate sid="location">7.481132 -6.50764 5.343665</translate>
+        <rotate sid="rotationZ">0 0 1 46.69194</rotate>
+        <rotate sid="rotationY">0 1 0 0.6197679</rotate>
+        <rotate sid="rotationX">1 0 0 63.55929</rotate>
+        <scale sid="scale">0.9999999 0.9999999 0.9999999</scale>
+        <instance_camera url="#Camera_001-camera"/>
+      </node>
+      <node id="Lamp_001" type="NODE">
+        <translate sid="location">4.076245 1.005454 5.903862</translate>
+        <rotate sid="rotationZ">0 0 1 106.9363</rotate>
+        <rotate sid="rotationY">0 1 0 3.163707</rotate>
+        <rotate sid="rotationX">1 0 0 37.26105</rotate>
+        <scale sid="scale">1 1 1</scale>
+        <instance_light url="#Lamp_001-light"/>
+      </node>
+      <node id="Cube" type="NODE">
+        <translate sid="location">0 0 0</translate>
+        <rotate sid="rotationZ">0 0 1 0</rotate>
+        <rotate sid="rotationY">0 1 0 0</rotate>
+        <rotate sid="rotationX">1 0 0 0</rotate>
+        <scale sid="scale">1 1 1</scale>
+        <instance_geometry url="#Cube-mesh">
+          <bind_material>
+            <technique_common>
+              <instance_material symbol="crate" target="#crate">
+                <bind_vertex_input semantic="UVTex" input_semantic="TEXCOORD" input_set="0"/>
+              </instance_material>
+            </technique_common>
+          </bind_material>
+        </instance_geometry>
+      </node>
+      <node id="Lamp" type="NODE">
+        <translate sid="location">4.076245 1.005454 5.903862</translate>
+        <rotate sid="rotationZ">0 0 1 106.9363</rotate>
+        <rotate sid="rotationY">0 1 0 3.163707</rotate>
+        <rotate sid="rotationX">1 0 0 37.26105</rotate>
+        <scale sid="scale">1 1 1</scale>
+        <instance_light url="#Lamp-light"/>
+      </node>
+      <node id="Camera" type="NODE">
+        <translate sid="location">7.481132 -6.50764 5.343665</translate>
+        <rotate sid="rotationZ">0 0 1 46.69194</rotate>
+        <rotate sid="rotationY">0 1 0 0.6197679</rotate>
+        <rotate sid="rotationX">1 0 0 63.55929</rotate>
+        <scale sid="scale">1 1 1</scale>
+        <instance_camera url="#Camera-camera"/>
+      </node>
+    </visual_scene>
+  </library_visual_scenes>
+  <scene>
+    <instance_visual_scene url="#Scene"/>
+  </scene>
+</COLLADA>

File game/assets/common/geometries/wscript

+#! /usr/bin/env python
+# encoding: utf-8
+
+from tools import utils
+from tools.compilers import dae
+
+
+def build(bld):
+    bld(name='geometries', rule=dae.run, color='CYAN',
+        source=bld.path.ant_glob('**/*.dae'))
+
+    bld.add_group()
+    bld.declare_chain(
+        name='compress_geometries',
+        rule=utils.compress,
+        color='BLUE',
+        ext_in='.geo',
+        ext_out='.geoz',
+        reentrant=False,
+    )
+    bld(dynamic_source='**/*.geo')

File game/assets/common/texts/test.csv

+"LABEL","FR","US","GB","JP"
+"TITLE","Titre","Title","Title","タイトル"
+"START","Démarrer","Start","Start","スタート"
+"COLOR","Couleur","Color","Colour","色"
+"NEWLINE","Un retour
+A la ligne","A new
+line","A new
+line","新しい
+ライン"
+"VARIABLE","Bonjour <var=player_name> !","Hello <var=player_name>!","Hello <var=player_name>!","こんにちは<var=player_name>!"
+"COMPLEX","Avec une, ça passe ?","With a, it's ok?","With a, it's ok?",
+"MORE_COMPLEX","Et avec ""ça"" ?","And with ""this""?","And with ""this""?","「これ」はどうですか"

File game/assets/common/texts/wscript

+#! /usr/bin/env python
+# encoding: utf-8
+
+from tools import utils
+from tools.compilers import csv_text
+
+
+def build(bld):
+    bld(name='texts', rule=csv_text.run, color='CYAN',
+        source=bld.path.ant_glob('**/*.csv'))
+
+    bld.add_group()
+    for lang in bld.env.languages:
+        bld.declare_chain(
+            name='compress_texts',
+            rule=utils.compress,
+            color='BLUE',
+            ext_in='.%s' % lang,
+            ext_out='.%sz' % lang,
+            reentrant=False,
+        )
+    bld(dynamic_source=' '.join('**/*.%s' % lang
+                                for lang in bld.env.languages))

File game/assets/common/textures/m00_obj_omake1.png

Added
New image

File game/assets/common/textures/wscript

+#! /usr/bin/env python
+# encoding: utf-8
+
+from tools import utils
+
+
+def build(bld):
+    bld.declare_chain(
+        name='textures',
+        rule=utils.copy,
+        color='GREEN',
+        ext_in='.png',
+        ext_out='.png.etc',
+        reentrant=True,
+    )
+    bld.declare_chain(
+        name='compress_textures',
+        rule=utils.compress,
+        color='BLUE',
+        ext_in='.etc',
+        ext_out='.etcz',
+        reentrant=False,
+    )
+    bld(source=bld.path.ant_glob('**/*.png'))

File game/assets/common/wscript

+#! /usr/bin/env python
+# encoding: utf-8
+
+
+def build(bld):
+    #bld.recurse('geometries')
+    bld.recurse('textures')
+    bld.recurse('texts')
+    bld.add_group()
+    #bld.recurse('fonts')

File game/assets/wscript

+#!/usr/bin/env python
+# encoding: utf-8
+
+from waflib import TaskGen, Utils, Build
+from tools import config, formats, pack
+from tools.formats.common import Data
+from tools.compilers import csv_text
+
+top = '.'
+out = '.build'
+
+
+@TaskGen.feature('*')
+@TaskGen.before('process_rule')
+def dynamic_post(self):
+    if not getattr(self, 'dynamic_source', None):
+        return
+    self.source = Utils.to_list(self.source)
+    self.source.extend(self.path.get_bld().ant_glob(self.dynamic_source))
+
+
+def options(opt):
+    config.options(opt)
+
+
+def configure(conf):
+    config.configure(conf)
+
+
+def build(bld):
+    if bld.env.m64:
+        Data.pointer = {
+            'cast': 'uint64_t',
+            'size': 8,
+            'repr': 'Q',
+        }
+    Data.endianness = '>' if bld.env.big_endian else '<'
+    bld.env.zip_module = __import__(bld.env.zip_module)
+    pack.File.padding = bld.env.padding
+
+    bld.post_mode = Build.POST_LAZY
+
+    for f in formats.__all__:
+        bld(rule=getattr(formats, f).export,
+            target='inc/formats/%s.h' % f, color='PINK')
+    bld.recurse('common')
+
+    bld.add_group()
+    bld(rule=pack.run, dynamic_source='**/*.etcz **/*.geoz **/*.bmfz',
+        target='game.pak pack.csv')
+    for lang in bld.env.languages:
+        bld(rule=pack.run, dynamic_source='**/*.%sz' % lang,
+            target='text_%s.pak text_%s.csv' % (lang, lang))
+    bld(rule=csv_text.write_tags, target='inc/texts/tags.h')

File game/engine/codec/base.h

+#ifndef __CODEC_BASE_H__
+#define __CODEC_BASE_H__
+
+#include <stdint.h>
+
+
+namespace codec {
+
+
+class Base {
+protected:
+    Base() : result_(0) {};
+
+public:
+    virtual ~Base()     {};
+
+    int get_result() { return result_; }
+    virtual bool has_error() = 0;
+
+    virtual bool init(uint8_t* output) = 0;
+    virtual bool finish() = 0;
+
+    virtual bool decode(uint8_t* output, uint32_t output_size, uint8_t* input,  uint32_t input_size) = 0;
+
+protected:
+    int     result_;
+};
+
+
+Base* create();
+
+
+} /* namespace codec */
+
+
+#endif

File game/engine/codec/factory.cpp

+#include "codec/base.h"
+#include "codec/zip.h"
+#include "codec/lzma.h"
+
+
+namespace codec {
+
+
+Base* create() {
+#if defined COMPRESSION_ZLIB
+    return new Zip();
+#elif defined COMPRESSION_LZMA
+    return new Lzma();
+#else
+    return 0; // NULL
+#endif
+}
+
+
+} /* namespace codec */

File game/engine/codec/lzma.h

+#ifdef COMPRESSION_LZMA
+#ifndef __CODEC_LZMA_H__
+#define __CODEC_LZMA_H__
+
+
+namespace codec {
+
+class Base;
+Base* create();
+
+
+class Lzma : public Base {
+    friend Base* create();
+
+protected:
+    Lzma();
+
+public:
+    virtual ~Lzma();
+
+    virtual bool has_error();
+
+    virtual bool init(uint8_t* output);
+    virtual bool finish();
+
+    virtual bool decode(uint8_t* output, uint32_t output_size, uint8_t* input,  uint32_t input_size);
+
+private:
+    void*    stream_;
+};
+
+
+} /* namespace codec */
+
+
+#endif
+#endif

File game/engine/codec/zip.cpp

+#ifdef COMPRESSION_ZLIB
+
+#include "codec/base.h"
+#include "codec/zip.h"
+
+#include <cstring>
+
+#ifdef MSVC
+    #define ZLIB_WINAPI
+#endif
+#include "zlib.h"
+
+
+namespace codec {
+
+
+Zip::Zip() :
+    Base(),
+    stream_(new z_stream)
+{}
+
+
+Zip::~Zip() {
+    delete stream_;
+}
+
+
+bool Zip::has_error() {
+    return result_ != Z_OK && result_ != Z_STREAM_END;
+}
+
+
+bool Zip::init(uint8_t* output) {
+    memset(stream_, 0, sizeof(z_stream));
+    stream_->next_out = reinterpret_cast<Bytef*>(output);
+    result_ = inflateInit(stream_);
+    return result_ == Z_OK;
+}
+
+
+bool Zip::finish() {
+    if (result_ == Z_STREAM_END)
+        return true;
+    result_ = inflateEnd(stream_);
+    return result_ == Z_STREAM_END;
+}
+
+
+bool Zip::decode(uint8_t* output, uint32_t output_size, uint8_t* input,  uint32_t input_size)
+{
+    if (output)
+        stream_->next_out = reinterpret_cast<Bytef*>(output);
+    stream_->next_in = reinterpret_cast<Bytef*>(input);
+    stream_->avail_in = input_size;
+    do {
+        stream_->avail_out = output_size;
+        result_ = inflate(stream_, Z_NO_FLUSH);
+        switch (result_) {
+            case Z_STREAM_ERROR:
+                return false;
+            case Z_NEED_DICT:
+                result_ = Z_DATA_ERROR;
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                inflateEnd(stream_);
+                return false;
+        }
+    } while (stream_->avail_out == 0);
+    return result_ != Z_STREAM_END;
+}
+
+
+} /* namespace codec */
+
+
+#endif

File game/engine/codec/zip.h

+#ifdef COMPRESSION_ZLIB
+
+#ifndef __CODEC_ZIP_H__
+#define __CODEC_ZIP_H__
+
+
+struct z_stream_s;
+typedef struct z_stream_s   z_stream;
+
+namespace codec {
+
+class Base;
+Base* create();
+
+
+class Zip : public Base {
+    friend Base* create();
+
+protected:
+    Zip();
+
+public:
+    virtual ~Zip();
+
+    virtual bool has_error();
+
+    virtual bool init(uint8_t* output);
+    virtual bool finish();
+
+    virtual bool decode(uint8_t* output, uint32_t output_size, uint8_t* input,  uint32_t input_size);
+
+private:
+    Zip(const Zip&);
+    Zip operator=(const Zip&);
+
+    z_stream*   stream_;
+};
+
+
+} /* namespace codec */
+
+
+#endif
+#endif

File game/engine/codec/zlma.cpp

+#ifdef COMPRESSION_LZMA
+
+#include "codec/base.h"
+#include "codec/lzma.h"
+
+#include <cstring>
+
+#include "lzma.h"
+
+
+namespace codec {
+
+
+Lzma::Lzma() : Base() {
+    stream_ = new lzma_stream;
+}
+
+
+Lzma::~Lzma() {
+    delete static_cast<lzma_stream*>(stream_);
+}
+
+
+bool Lzma::has_error() {
+    return result_ != LZMA_OK && result_ != LZMA_FINISH;
+}
+
+
+bool Lzma::init(uint8_t* output) {
+    lzma_stream* stream = static_cast<lzma_stream*>(stream_);
+    memset(stream, 0, sizeof(lzma_stream));
+    stream->next_out = output;
+    result_ = lzma_stream_decoder(stream, UINT64_MAX, LZMA_CONCATENATED);
+    return result_ == LZMA_OK;
+}
+
+
+bool Lzma::finish() {
+    if (result_ == LZMA_STREAM_END)
+        return true;
+    result_ = lzma_code(static_cast<lzma_stream*>(stream_), LZMA_FINISH);
+    return result_ == LZMA_STREAM_END;
+}
+
+
+bool Lzma::decode(uint8_t* output, uint32_t output_size, uint8_t* input,  uint32_t input_size)
+{
+    lzma_stream* stream = static_cast<lzma_stream*>(stream_);
+    if (output)
+        stream->next_out = output;
+    stream->next_in = input;
+    stream->avail_in = input_size;
+    do {
+        stream->avail_out = output_size;
+        result_ = lzma_code(stream, LZMA_RUN);
+        if (result_ != LZMA_OK)
+            return false;
+    } while (stream->avail_out == 0);
+    return result_ != LZMA_STREAM_END;
+}
+
+
+} /* namespace codec */
+
+
+#endif

File game/engine/common/intrusive_list.cpp

+#include "common/intrusive_list.h"
+
+namespace common {
+
+
+ListNode::ListNode() {
+    prev_ = this;
+    next_ = this;
+}
+
+
+ListNode::~ListNode() {
+    unlink();
+}
+
+
+void ListNode::unlink() {
+    if (!is_linked())
+        return;
+
+    prev_->next_ = next_;
+    next_->prev_ = prev_;
+    prev_ = next_ = this;
+}
+
+
+void ListNode::insert_after(ListNode* node) {
+    unlink();
+
+    prev_ = node;
+    next_ = node->next_;
+
+    prev_->next_ = this;
+    next_->prev_ = this;
+}
+
+
+void ListNode::insert_before(ListNode* node) {
+    unlink();
+
+    next_ = node;
+    prev_ = node->prev_;
+
+    next_->prev_ = this;
+    prev_->next_ = this;
+}
+
+
+} /* namespace common */

File game/engine/common/intrusive_list.h

+#ifndef __COMMON_LIST_H__
+#define __COMMON_LIST_H__
+
+
+#include <stddef.h>
+
+
+#define INTRUSIVE_LIST(T, node)       common::ListDeclare<T, offsetof(T, node)>()
+
+
+namespace common {
+
+
+class ListNode {
+public:
+        ListNode();
+        ~ListNode();
+
+        ListNode* next() { return next_; }
+        ListNode* prev() { return prev_; }
+
+        bool is_linked() const { return next_ != prev_; }
+        void unlink();
+
+        void insert_after(ListNode* node);
+        void insert_before(ListNode* node);
+
+private:
+    ListNode(const ListNode&);
+    ListNode& operator= (const ListNode&);
+
+    ListNode*   prev_;
+    ListNode*   next_;
+};
+
+
+
+// -----------------------------------------------------------------------------
+
+template <class T>
+class List {
+public:
+    ~List();
+
+    T* first();
+    T* last();
+    T* next(T* object);
+    T* prev(T* object);
+    ListNode* get_node(T* object) const;
+    T* get_object(ListNode* node) const;
+
+    bool is_empty() const;
+    void push_back(T* object);
+    void push_front(T* object);
+
+private:
+    List(size_t offset) : offset_(offset) {}
+
+    size_t      offset_;
+    ListNode    root_;
+
+    template<class, size_t> friend class ListDeclare;
+};
+
+
+template <class T>
+List<T>::~List() {
+    while (root_.is_linked())
+        root_.next()->unlink();
+}
+
+
+template <class T>
+T* List<T>::first() {
+    return root_.is_linked() ? get_object(root_.next()) : NULL;
+}
+
+
+template <class T>
+T* List<T>::last() {
+    return root_.is_linked() ? get_object(root_.prev()) : NULL;
+}
+
+
+template <class T>
+T* List<T>::next(T* object) {
+    ListNode* node = get_node(object);
+    if (node->next() == &root_)
+        return NULL;
+    else
+        return get_object(node->next());
+}
+
+
+template <class T>
+T* List<T>::prev(T* object) {
+    ListNode* node = get_node(object);
+    if (node->prev() == &root_)
+        return NULL;
+    else
+        return get_object(node->prev());
+}
+
+
+template <class T>
+ListNode* List<T>::get_node(T* object) const {
+    return reinterpret_cast<ListNode*>(reinterpret_cast<size_t>(object) + offset_);
+}
+
+
+template <class T>
+T* List<T>::get_object(ListNode* node) const {
+    return reinterpret_cast<T*>(reinterpret_cast<size_t>(node) - offset_);
+}
+
+
+template <class T>
+void List<T>::push_back(T* object) {
+    get_node(object)->insert_before(&root_);
+}
+
+
+template <class T>
+void List<T>::push_front(T* object) {
+    get_node(object)->insert_after(&root_);
+}
+
+
+// -----------------------------------------------------------------------------
+
+
+template <class T, size_t offset>
+class ListDeclare : public List<T> {
+public:
+    ListDeclare();
+};
+
+
+template <class T, size_t offset>
+ListDeclare<T, offset>::ListDeclare() : List<T>(offset)
+{}
+
+
+} /* namespace common */
+
+
+#endif

File game/engine/common/log.cpp

+#if defined(DEBUG)
+
+
+#include "common/log.h"
+
+
+#include <stdarg.h>
+#include <cstring>
+#include <cstdio>
+
+namespace common {
+
+
+#define LOG_BUFFER_SIZE     256
+
+
+Log::log_map_t    Log::allocated_;
+
+
+Log::Log(const char* context) :
+    context_length_(0),
+    threshold_(Log::LOG_DEBUG)
+{
+    buffer_ = new char [LOG_BUFFER_SIZE];
+
+    context_length_ = strlen(context);
+    if (context_length_ > LOG_BUFFER_SIZE)
+        context_length_ = LOG_BUFFER_SIZE / 2;
+
+    sprintf(buffer_, "[%s] ", context);
+    context_length_ = strlen(buffer_);
+}
+
+
+Log::~Log() {
+    delete buffer_;
+}
+
+
+Log* Log::get(const char* context) {
+    log_map_t::iterator it = allocated_.find(context);
+    if (it != allocated_.end())
+        return it->second;
+
+    Log* log = new Log(context);
+    allocated_[context] = log;
+    return log;
+}
+
+
+void Log::clear() {
+    for (log_map_t::iterator it = allocated_.begin(); it != allocated_.end(); ++it)
+        delete it->second;
+    allocated_.clear();
+}
+
+
+void Log::write(Log::log_level_e log_level, const char* format, ...) {
+    if (threshold_ > log_level)
+        return;
+
+    switch (log_level) {
+        case LOG_DEBUG:
+            printf("    ");
+            break;
+        case LOG_INFO:
+            printf("-I- ");
+            break;
+        case LOG_WARNING:
+            printf("+W+ ");
+            break;
+        case LOG_ERROR:
+            printf("*E* ");
+            break;
+    }
+
+    va_list arg_list;
+    va_start(arg_list, format);
+    vsnprintf(buffer_ + context_length_,
+              LOG_BUFFER_SIZE - context_length_,
+              format, arg_list);
+    va_end(arg_list);
+
+    printf("%s", buffer_);
+
+    fflush(stdout);
+}
+
+
+} /* namespace common */
+
+
+#endif // defined(DEBUG)

File game/engine/common/log.h

+#ifndef _COMMON_LOG_
+#define _COMMON_LOG_
+
+
+#if defined(DEBUG)
+
+
+#include <map>
+#include <string>
+
+
+#define LOG(...)                { if (log_) log_->write(common::Log::LOG_DEBUG, __VA_ARGS__); }
+#define LOG_I(...)              { if (log_) log_->write(common::Log::LOG_INFO, __VA_ARGS__); }
+#define LOG_W(...)              { if (log_) log_->write(common::Log::LOG_WARNING, __VA_ARGS__); }
+#define LOG_E(...)              { if (log_) log_->write(common::Log::LOG_ERROR, __VA_ARGS__); }
+
+
+namespace common {
+
+
+class Log {
+public:
+
+    enum log_level_e {
+        LOG_DEBUG,
+        LOG_INFO,
+        LOG_WARNING,
+        LOG_ERROR
+    };
+
+    static Log* get(const char* context);
+    static void clear();
+
+    void write(log_level_e log_level, const char* format, ...);
+    void set_log_threshold(log_level_e log_level=LOG_DEBUG);
+
+private:
+    Log(const char* context);
+    virtual ~Log();
+
+    char*   buffer_;
+    int     context_length_;
+    log_level_e threshold_;
+
+    typedef std::map<std::string, Log*> log_map_t;
+    static log_map_t    allocated_;
+};
+
+
+} /* namespace common */
+
+
+#else // defined(DEBUG)
+
+#define LOG(...)        {}
+#define LOG_I(...)      {}
+#define LOG_W(...)      {}
+#define LOG_E(...)      {}
+
+#endif // defined(DEBUG)
+
+
+
+#endif

File game/engine/common/singleton.h

+#ifndef _COMMON_SINGLETON_
+#define _COMMON_SINGLETON_
+
+
+namespace common {
+
+
+template <class T>
+class Singleton {
+public:
+    static inline T* instance() {
+        static T instance;
+        return &instance;
+    }
+
+protected:
+    Singleton() {}
+    ~Singleton() {}
+};
+
+
+} /* namespace common */
+
+
+#endif

File game/engine/io/file/base.h

+#ifndef __IO_FILE_BASE_H__
+#define __IO_FILE_BASE_H__
+
+#include <cstddef>
+#include <stdint.h>
+
+
+namespace io { namespace file {
+
+
+class Base {
+public:
+    Base() {}
+    virtual ~Base() {}
+
+    virtual bool open(const char* filename, const char* mode) = 0;
+    virtual bool is_open() const = 0;
+    virtual void close() = 0;
+
+    virtual void seek(uint64_t offset) = 0;
+    virtual uint64_t tell() const = 0;
+
+    virtual size_t read(uint8_t* buffer, size_t size, size_t count) = 0;
+    virtual size_t write(const uint8_t* buffer, size_t size, size_t count) = 0;
+
+    virtual size_t size() = 0;
+    virtual uint8_t* read() = 0;
+};
+
+
+} /* namespace file */ } /* namespace io */
+
+
+#endif

File game/engine/io/file/decoder.cpp

+#include "io/file/decoder.h"
+
+#include <algorithm>
+
+#include "codec/base.h"
+#include "io/file/base.h"
+
+
+namespace io { namespace file {
+
+enum {
+    DECODER_SIZE = 16 * 1024
+};
+
+
+Decoder::Decoder() :
+    codec_(codec::create()),
+    size_(DECODER_SIZE),
+    buffer_(new uint8_t [size_])
+{
+}
+
+
+Decoder::~Decoder() {
+    delete codec_;
+    delete buffer_;
+}
+
+
+uint8_t* Decoder::decode(Base* file, uint32_t input_size, uint32_t output_size) {
+    uint64_t size = input_size;
+    uint8_t* output = new uint8_t [output_size];
+    if (!codec_->init(output)) {
+        delete output;
+        return NULL;
+    }
+    do {
+        size = file->read(buffer_, sizeof(uint8_t), std::min(input_size, size_));
+        input_size -= size;
+    } while (codec_->decode(NULL, output_size, buffer_, size) && input_size > 0);
+    if (!codec_->finish()) {
+        delete output;
+        return NULL;
+    }
+    return output;
+}
+
+
+} /* namespace io */ } /* namespace file */

File game/engine/io/file/decoder.h

+#ifndef __IO_FILE_DECODER_H__
+#define __IO_FILE_DECODER_H__
+
+
+#include <stdint.h>
+
+
+namespace codec {
+    class Base;
+}
+
+namespace io { namespace file {
+
+class Base;
+
+
+class Decoder {
+public:
+    Decoder();
+    ~Decoder();
+
+    uint8_t* decode(Base* file, uint32_t input_size, uint32_t output_size);
+
+private:
+    Decoder(const Decoder&);
+    Decoder operator=(const Decoder&);
+
+    ::codec::Base*  codec_;
+    uint32_t    size_;
+    uint8_t*    buffer_;
+};
+
+
+} /* namespace file */ } /* namespace io */
+
+
+#endif

File game/engine/io/file/stdio.cpp

+#include "io/file/base.h"
+#include "io/file/stdio.h"
+
+
+namespace io { namespace file {
+
+
+Stdio::Stdio() : file_(NULL) {
+
+}
+
+
+Stdio::~Stdio() {
+    close();
+    file_ = NULL;
+}
+
+
+bool Stdio::open(const char* filename, const char* mode) {
+    file_ = fopen(filename, mode);
+    return is_open();
+}
+
+
+bool Stdio::is_open() const {
+    return file_ != NULL;
+}
+
+
+void Stdio::close() {
+    if (!is_open())
+        return;
+    fclose(file_);
+    file_ = NULL;
+}
+
+
+void Stdio::seek(uint64_t offset) {
+    if (!is_open())
+        return;
+    fseek(file_, offset, SEEK_SET);
+}
+
+
+uint64_t Stdio::tell() const {
+    if (!is_open())
+        return -1;
+    return ftell(file_);
+}
+
+
+size_t Stdio::read(uint8_t* buffer, size_t size, size_t count) {
+    if (!is_open())
+        return -1;
+    return fread(buffer, size, count, file_);
+}
+
+
+size_t Stdio::write(const uint8_t* buffer, size_t size, size_t count) {
+    if (!is_open())
+        return -1;
+    return fwrite(buffer, size, count, file_);
+}
+
+
+size_t Stdio::size() {
+    if (!is_open())
+        return -1;
+
+    size_t size = 0;
+    uint64_t offset = tell();
+
+    fseek(file_, 0, SEEK_END);
+    size = tell();
+    seek(offset);
+
+    return size;
+}
+
+
+uint8_t* Stdio::read() {
+    if (!is_open())
+        return NULL;
+
+    size_t buf_size = size();
+    uint8_t* buffer = new uint8_t [buf_size];
+
+    read(buffer, sizeof(uint8_t), buf_size);
+
+    return buffer;
+}
+
+
+} /* namespace file */ } /* namespace io */

File game/engine/io/file/stdio.h

+#ifndef __IO_FILE_STDIO_H__
+#define __IO_FILE_STDIO_H__
+
+#include <cstdio>
+#include <stdint.h>
+
+
+namespace io { namespace file {
+
+class Base;
+
+
+class Stdio : public Base {
+public:
+    Stdio();
+    virtual ~Stdio();
+
+    virtual bool open(const char* filename, const char* mode);
+    virtual bool is_open() const;
+    virtual void close();
+
+    virtual void seek(uint64_t offset);
+    virtual uint64_t tell() const;
+
+    virtual size_t read(uint8_t* buffer, size_t size, size_t count);
+    virtual size_t write(const uint8_t* buffer, size_t size, size_t count);
+
+    virtual size_t size();
+    virtual uint8_t* read();
+
+private:
+    Stdio(const Stdio&);
+    Stdio operator=(const Stdio&);
+
+    FILE*   file_;
+};
+
+
+} /* namespace file */ } /* namespace io */
+
+
+#endif

File game/engine/io/fs/base.cpp

+#include "io/file/base.h"
+#include "io/fs/base.h"
+
+#include "io/file/stdio.h"
+
+
+namespace io { namespace fs {
+
+
+::io::file::Base* Base::open(const char* filename, const char* mode) const {
+    ::io::file::Base* file = new ::io::file::Stdio();
+
+    if (file->open(filename, mode))
+        return file;
+
+    delete file;
+    return NULL;
+}
+
+
+uint8_t* Base::read(const char* filename, const char* mode) const {
+    ::io::file::Base* file = open(filename, mode);
+
+    if (!file)
+        return NULL;
+
+    uint8_t* buffer = file->read();
+
+    delete file;
+    return buffer;
+}
+
+
+uint8_t* Base::read(const uint32_t& h, const char* mode) const {
+    return NULL;
+}
+
+
+} /* namespace fs */ } /* namespace io */

File game/engine/io/fs/base.h

+#ifndef __IO_FS_BASE_H__
+#define __IO_FS_BASE_H__
+
+
+#include <stdint.h>
+
+
+namespace io { namespace file {
+    class Base;
+} /* namespace file */
+
+namespace fs {
+
+
+class Base {
+    friend Base* create();
+
+protected:
+    Base() {}
+
+public:
+    virtual ~Base() {}
+
+    virtual ::io::file::Base* open(const char* filename, const char* mode="rb") const;
+    virtual uint8_t* read(const char* filename, const char* mode="rb") const;
+    virtual uint8_t* read(const uint32_t& h, const char* mode="rb") const;
+};
+
+
+Base* create();
+Base* open(const char* filename);
+
+
+} /* namespace fs */ } /* namespace io */
+
+
+#endif

File game/engine/io/fs/factory.cpp

+#include "io/fs/base.h"
+#include "io/fs/pack.h"
+
+
+namespace io { namespace fs {
+
+
+Base* create() {
+    return new Base();
+}
+
+
+Base* open(const char* filename) {
+    Base* fs = create();
+    ::io::file::Base* pack = fs->open(filename);
+    delete fs;
+
+    if (!pack)
+        return NULL;
+
+    Pack* fs_pack = new Pack();
+    fs_pack->init(pack);
+    return fs_pack;
+}
+
+
+} /* namespace fs */ } /* namespace io */

File game/engine/io/fs/pack.cpp

+//#define DUMP_FILE
+
+#include "io/fs/base.h"
+#include "io/fs/pack.h"
+
+#include "io/file/decoder.h"
+#include "io/file/base.h"
+
+#include "formats/pack.h"
+
+
+namespace io { namespace fs {
+
+
+Pack::Pack() :
+    Base(),
+    header_(NULL),
+    mft_(NULL),
+    pack_(NULL),
+    decoder_(NULL)
+{}
+
+
+void Pack::init(::io::file::Base* pack) {
+    using namespace ::io::file;
+    using namespace ::formats::pack;
+
+    pack_ = pack;
+    decoder_ = new Decoder();
+
+    uint8_t* buffer = new uint8_t [HEADER_SIZE];
+    pack_->read(buffer, sizeof(uint8_t), HEADER_SIZE);
+    header_ = Header::allocate(buffer);
+
+    buffer = new uint8_t [header_->mft_size];
+    pack_->read(buffer, sizeof(uint8_t), header_->mft_size);
+    mft_ = MFT::allocate(buffer);
+
+    for (unsigned int i = 0; i < mft_->files_size; ++i)
+        files_[mft_->files[i].hash] = &mft_->files[i];
+}
+
+
+Pack::~Pack() {