new version commit

This commit is contained in:
mikx
2025-09-29 02:27:58 -04:00
commit 3e8d31e686
9244 changed files with 7357899 additions and 0 deletions

6
deps/libmpq/bindings/Makefile.am vendored Normal file
View File

@@ -0,0 +1,6 @@
# any directories which should be built and installed.
SUBDIRS = d
if HAVE_PYTHON
SUBDIRS += python
endif

6
deps/libmpq/bindings/d/Makefile.am vendored Normal file
View File

@@ -0,0 +1,6 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# install D binding to /usr/include/d by default
libmpq_includedir = $(includedir)/d
libmpq_include_HEADERS = mpq.d

2
deps/libmpq/bindings/d/dsss.conf vendored Normal file
View File

@@ -0,0 +1,2 @@
[mpq.d]
type=sourcelibrary

318
deps/libmpq/bindings/d/mpq.d vendored Normal file
View File

@@ -0,0 +1,318 @@
/*
* mpq.d -- D programming language module for libmpq
*
* Copyright (c) 2008 Georg Lukas <georg@op-co.de>
*
* 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 should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* This module is written to support Phobos. Patches to allow binding to
* Tango are welcome.
*/
module mpq;
/* the following pragma does not work on DMD/Linux, generates a warning on
* GDC/Linux and has not been tested on Windows. Commented out for now. */
// pragma(lib, "libmpq");
import std.string; // for format() and toStringz()
import std.traits; // for ParameterTypeTuple!()
/* XXX: this assumes that libmpq is compiled with Large File Support on */
alias long off_t;
/* libmpq error return values */
const LIBMPQ_ERROR_OPEN = -1; /* open error on file. */
const LIBMPQ_ERROR_CLOSE = -2; /* close error on file. */
const LIBMPQ_ERROR_SEEK = -3; /* lseek error on file. */
const LIBMPQ_ERROR_READ = -4; /* read error on file. */
const LIBMPQ_ERROR_WRITE = -5; /* write error on file. */
const LIBMPQ_ERROR_MALLOC = -6; /* memory allocation error. */
const LIBMPQ_ERROR_FORMAT = -7; /* format errror. */
const LIBMPQ_ERROR_NOT_INITIALIZED = -8; /* init() wasn't called. */
const LIBMPQ_ERROR_SIZE = -9; /* buffer size is to small. */
const LIBMPQ_ERROR_EXIST = -10; /* file or block does not exist in archive. */
const LIBMPQ_ERROR_DECRYPT = -11; /* we don't know the decryption seed. */
const LIBMPQ_ERROR_UNPACK = -12; /* error on unpacking file. */
/** libmpq internal meta-data for an archive */
extern struct mpq_archive_s;
extern(C) {
/* libmpq__generic information about library. */
char *libmpq__version();
/* libmpq__generic mpq archive information. */
int libmpq__archive_open(mpq_archive_s **mpq_archive, char *mpq_filename, off_t archive_offset);
int libmpq__archive_close(mpq_archive_s *mpq_archive);
int libmpq__archive_packed_size(mpq_archive_s *mpq_archive, off_t *packed_size);
int libmpq__archive_unpacked_size(mpq_archive_s *mpq_archive, off_t *unpacked_size);
int libmpq__archive_offset(mpq_archive_s *mpq_archive, off_t *offset);
int libmpq__archive_version(mpq_archive_s *mpq_archive, uint *version_);
int libmpq__archive_files(mpq_archive_s *mpq_archive, uint *files);
/* libmpq__generic file processing functions. */
int libmpq__file_packed_size(mpq_archive_s *mpq_archive, uint file_number, off_t *packed_size);
int libmpq__file_unpacked_size(mpq_archive_s *mpq_archive, uint file_number, off_t *unpacked_size);
int libmpq__file_offset(mpq_archive_s *mpq_archive, uint file_number, off_t *offset);
int libmpq__file_blocks(mpq_archive_s *mpq_archive, uint file_number, uint *blocks);
int libmpq__file_encrypted(mpq_archive_s *mpq_archive, uint file_number, uint *encrypted);
int libmpq__file_compressed(mpq_archive_s *mpq_archive, uint file_number, uint *compressed);
int libmpq__file_imploded(mpq_archive_s *mpq_archive, uint file_number, uint *imploded);
int libmpq__file_number(mpq_archive_s *mpq_archive, char *filename, uint *number);
int libmpq__file_read(mpq_archive_s *mpq_archive, uint file_number, ubyte *out_buf, off_t out_size, off_t *transferred);
/* libmpq__generic block processing functions. */
int libmpq__block_open_offset(mpq_archive_s *mpq_archive, uint file_number);
int libmpq__block_close_offset(mpq_archive_s *mpq_archive, uint file_number);
int libmpq__block_unpacked_size(mpq_archive_s *mpq_archive, uint file_number, uint block_number, off_t *unpacked_size);
int libmpq__block_read(mpq_archive_s *mpq_archive, uint file_number, uint block_number, ubyte *out_buf, off_t out_size, off_t *transferred);
}
/** exception class for failed libmpq calls */
class MPQException : Exception {
const string[] Errors = [
"unknown error",
"open error on file",
"close error on file",
"lseek error on file",
"read error on file",
"write error on file",
"memory allocation error",
"format errror",
"init() wasn't called",
"buffer size is to small",
"file or block does not exist in archive",
"we don't know the decryption seed",
"error on unpacking file"];
public int errno;
this(char[] fnname = "unknown_function", int errno = 0) {
this.errno = errno;
if (-errno >= Errors.length)
errno = 0;
super(std.string.format("Error in %s(): %s (%d)",
fnname, Errors[-errno], errno));
}
}
/** template to wrap function calls and throw exceptions in case of error
*
* thanks for the idea to while(nan) blog,
* http://while-nan.blogspot.com/2007/06/wrapping-functions-for-fun-and-profit.html
*
* use: MPQ_CHECKERR(libmpq__archive_open)(&m, "foo.mpq", -1);
* returns the retval of archive_open on success;
* throws an MPQException on failure.
*
* @param Fn libmpq__function reference
* @param args libmpq__function parameters
* @return return value of libmpq__function on success
* @throw MPQException on error
*/
int MPQ_CHECKERR(alias Fn)(ParameterTypeTuple!(Fn) args)
{
int result = Fn(args);
if (result < 0) {
/* XXX: relying on non-specified stringof() behaviour */
throw new MPQException((&Fn).stringof[2..$], result);
}
return result;
}
/** mixin alias to wrap library functions into MPQ_CHECKERR.
*
* alias mpq.func_name(...) to MPQ_CHECKERR(libmpq__func_name)(...)
* @param func_name name of the function to be wrapped
*/
template MPQ_FUNC(char[] func_name) {
const char[] MPQ_FUNC = "alias MPQ_CHECKERR!(libmpq__" ~ func_name ~ ") " ~ func_name ~ ";";
}
alias libmpq__version libversion; /* must be direct alias because it returns char*, not error int */
mixin(MPQ_FUNC!("archive_open"));
mixin(MPQ_FUNC!("archive_close"));
mixin(MPQ_FUNC!("archive_packed_size"));
mixin(MPQ_FUNC!("archive_unpacked_size"));
mixin(MPQ_FUNC!("archive_offset"));
mixin(MPQ_FUNC!("archive_version"));
mixin(MPQ_FUNC!("archive_files"));
mixin(MPQ_FUNC!("file_packed_size"));
mixin(MPQ_FUNC!("file_unpacked_size"));
mixin(MPQ_FUNC!("file_offset"));
mixin(MPQ_FUNC!("file_blocks"));
mixin(MPQ_FUNC!("file_encrypted"));
mixin(MPQ_FUNC!("file_compressed"));
mixin(MPQ_FUNC!("file_imploded"));
mixin(MPQ_FUNC!("file_number"));
mixin(MPQ_FUNC!("file_read"));
mixin(MPQ_FUNC!("block_open_offset"));
mixin(MPQ_FUNC!("block_close_offset"));
mixin(MPQ_FUNC!("block_unpacked_size"));
mixin(MPQ_FUNC!("block_read"));
/** getter function named name for returning archive_* single values:
*
* <type> Archive.<name>() { return libmpq__archive_<name>() }
*
* @param type return type for the original function reference
* @param name name of the original function
* @param name2 name for the prototype (defaults to name, used for "version")
* @return getter function mixin
*/
template MPQ_A_GET(char[] type, char[] name, char[] name2 = name) {
const char[] MPQ_A_GET = type ~ " " ~ name2 ~ "() { " ~
type ~ " ret; " ~
"archive_" ~ name ~ "(m, &ret); return ret;" ~
"}";
}
/** wrapper class for an MPQ Archive
*
* syntax: auto a = new mpq.Archive("somefile.mpq");
*/
class Archive {
mpq_archive_s *m;
File listfile;
char[][] listfiledata;
this(char[] archivename, off_t offset = -1) {
archive_open(&m, toStringz(archivename), offset);
}
mixin(MPQ_A_GET!("off_t", "packed_size"));
mixin(MPQ_A_GET!("off_t", "unpacked_size"));
mixin(MPQ_A_GET!("off_t", "offset"));
mixin(MPQ_A_GET!("uint", "version", "version_"));
mixin(MPQ_A_GET!("uint", "files"));
~this() {
archive_close(m);
}
mpq_archive_s* archive() {
return m;
}
File opIndex(char[] fname) {
return new File(this, fname);
}
File opIndex(int fno) {
return new File(this, fno);
}
char[][] filelist() {
try {
if (!listfile) {
listfile = this["(listfile)"];
listfiledata = (cast(char[])listfile.read()).splitlines();
}
return listfiledata;
} catch (MPQException e) {
return [];
}
}
/+uint filenumber(char[] filename) {
try {
if (!listfile) {
listfile = this["(listfile)"];
listfiledata = (cast(char[])listfile.read()).splitlines();
}
return listfiledata;
} catch (MPQException e) {
return [];
}
}+/
}
/** getter function named name for returning file_* single values:
*
* <type> File.<name>() { return libmpq__file_<name>() }
*
* @param type return type for the original function reference
* @param name name of the original function
* @param name2 name for the prototype (defaults to name, used for "version")
* @return getter function mixin
*/
template MPQ_F_GET(char[] type, char[] name, char[] name2 = name) {
const char[] MPQ_F_GET = type ~ " " ~ name2 ~ "() { " ~
type ~ " ret; " ~
"file_" ~ name ~ "(am, fileno, &ret); " ~
"return ret;" ~
"}";
}
/** wrapper class for a single file in an MPQ Archive
*
* syntax:
* auto a = new mpq.Archive("somefile.mpq");
* auto f = a["(listfile)"];
* auto f2 = a[0];
* auto f3 = new File(a, "(listfile)");
*/
class File {
Archive a;
mpq_archive_s* am;
char[] filename;
uint fileno;
this(Archive a, int fileno) {
this.a = a;
this.am = a.archive();
if (fileno >= a.files) {
throw new MPQException(format("File(%d)", fileno),
LIBMPQ_ERROR_EXIST);
}
this.filename = format("file%04d.xxx", fileno);
this.fileno = fileno;
}
this(Archive a, char[] filename) {
this.a = a;
this.am = a.archive();
this.filename = filename;
/* this line will throw an exception when the file is not there */
mpq.file_number(am, toStringz(filename), &this.fileno);
}
mixin(MPQ_F_GET!("off_t", "packed_size"));
mixin(MPQ_F_GET!("off_t", "unpacked_size"));
mixin(MPQ_F_GET!("off_t", "offset"));
mixin(MPQ_F_GET!("uint", "blocks"));
mixin(MPQ_F_GET!("uint", "encrypted"));
mixin(MPQ_F_GET!("uint", "compressed"));
mixin(MPQ_F_GET!("uint", "imploded"));
uint no() { return fileno; }
char[] name() { return filename; }
ubyte[] read() {
ubyte[] content;
content.length = this.unpacked_size();
off_t trans;
mpq.file_read(am, fileno, content.ptr, content.length, &trans);
content.length = trans;
return content;
}
}

View File

@@ -0,0 +1,5 @@
# minimum required automake 1.6
AUTOMAKE_OPTIONS = 1.6
# library information and headers which should not be installed.
python_PYTHON = mpq.py

16
deps/libmpq/bindings/python/mpq-info vendored Normal file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env python
from __future__ import division
import sys
import mpq
archive = mpq.Archive(sys.argv[1])
print "Name: %s" % sys.argv[1]
print "Version: %s" % archive.filename
print "Offset: %s" % archive.offset
print "Packed size: %s" % archive.packed_size
print "Unpacked size: %s" % archive.unpacked_size
print "Compression ratio: %s" % (archive.packed_size/archive.unpacked_size)

322
deps/libmpq/bindings/python/mpq.py vendored Normal file
View File

@@ -0,0 +1,322 @@
"""wrapper for libmpq"""
# 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 should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import ctypes
import ctypes.util
import os
libmpq = ctypes.CDLL(ctypes.util.find_library("mpq"))
class Error(Exception):
pass
errors = {
-1: (IOError, "open"),
-2: (IOError, "close"),
-3: (IOError, "seek"),
-4: (IOError, "read"),
-5: (IOError, "write"),
-6: (MemoryError,),
-7: (Error, "file is not an mpq or is corrupted"),
-8: (AssertionError, "not initialized"),
-9: (AssertionError, "buffer size too small"),
-10: (IndexError, "file not in archive"),
-11: (AssertionError, "decrypt"),
-12: (AssertionError, "unpack"),
}
def check_error(result, func, arguments, errors=errors):
try:
error = errors[result]
except KeyError:
return result
else:
raise error[0](*error[1:])
libmpq.libmpq__version.restype = ctypes.c_char_p
libmpq.libmpq__archive_open.errcheck = check_error
libmpq.libmpq__archive_close.errcheck = check_error
libmpq.libmpq__archive_packed_size.errcheck = check_error
libmpq.libmpq__archive_unpacked_size.errcheck = check_error
libmpq.libmpq__archive_offset.errcheck = check_error
libmpq.libmpq__archive_version.errcheck = check_error
libmpq.libmpq__archive_files.errcheck = check_error
libmpq.libmpq__file_packed_size.errcheck = check_error
libmpq.libmpq__file_unpacked_size.errcheck = check_error
libmpq.libmpq__file_offset.errcheck = check_error
libmpq.libmpq__file_blocks.errcheck = check_error
libmpq.libmpq__file_encrypted.errcheck = check_error
libmpq.libmpq__file_compressed.errcheck = check_error
libmpq.libmpq__file_imploded.errcheck = check_error
libmpq.libmpq__file_number.errcheck = check_error
libmpq.libmpq__file_read.errcheck = check_error
libmpq.libmpq__block_open_offset.errcheck = check_error
libmpq.libmpq__block_close_offset.errcheck = check_error
libmpq.libmpq__block_unpacked_size.errcheck = check_error
libmpq.libmpq__block_read.errcheck = check_error
__version__ = libmpq.libmpq__version()
class Reader(object):
def __init__(self, file, libmpq=libmpq):
self._file = file
self._pos = 0
self._buf = []
self._cur_block = 0
libmpq.libmpq__block_open_offset(self._file._archive._mpq,
self._file.number)
def __iter__(self):
return self
def __repr__(self):
return "iter(%r)" % self._file
def seek(self, offset, whence=os.SEEK_SET, os=os):
if whence == os.SEEK_SET:
pass
elif whence == os.SEEK_CUR:
offset += self._pos
elif whence == os.SEEK_END:
offset += self._file.unpacked_size
else:
raise ValueError, "invalid whence"
if offset >= self._pos:
self.read(offset - self._pos)
else:
self._pos = 0
self._buf = []
self._cur_block = 0
self.read(offset)
def tell(self):
return self._pos
def _read_block(self, ctypes=ctypes, libmpq=libmpq):
block_size = ctypes.c_uint64()
libmpq.libmpq__block_unpacked_size(self._file._archive._mpq,
self._file.number, self._cur_block, ctypes.byref(block_size))
block_data = ctypes.create_string_buffer(block_size.value)
libmpq.libmpq__block_read(self._file._archive._mpq,
self._file.number, self._cur_block,
block_data, ctypes.c_uint64(len(block_data)), None)
self._buf.append(block_data.raw)
self._cur_block += 1
def read(self, size=-1):
while size < 0 or sum(map(len, self._buf)) < size:
if self._cur_block == self._file.blocks:
break
self._read_block()
buf = "".join(self._buf)
if size < 0:
ret = buf
self._buf = []
else:
ret = buf[:size]
self._buf = [buf[size:]]
self._pos += len(ret)
return ret
def readline(self, os=os):
line = []
while True:
char = self.read(1)
if char == "":
break
if char not in '\r\n' and line and line[-1] in '\r\n':
self.seek(-1, os.SEEK_CUR)
break
line.append(char)
return ''.join(line)
def next(self):
line = self.readline()
if not line:
raise StopIteration
return line
def readlines(self, sizehint=-1):
res = []
while sizehint < 0 or sum(map(len, res)) < sizehint:
line = self.readline()
if not line:
break
res.append(line)
return res
xreadlines = __iter__
def __del__(self, libmpq=libmpq):
libmpq.libmpq__block_close_offset(self._file._archive._mpq,
self._file.number)
class File(object):
def __init__(self, archive, number, ctypes=ctypes, libmpq=libmpq):
self._archive = archive
self.number = number
for name, atype in [
("packed_size", ctypes.c_uint64),
("unpacked_size", ctypes.c_uint64),
("offset", ctypes.c_uint64),
("blocks", ctypes.c_uint32),
("encrypted", ctypes.c_uint32),
("compressed", ctypes.c_uint32),
("imploded", ctypes.c_uint32),
]:
data = atype()
func = getattr(libmpq, "libmpq__file_"+name)
func(self._archive._mpq, self.number, ctypes.byref(data))
setattr(self, name, data.value)
def __str__(self, ctypes=ctypes, libmpq=libmpq):
data = ctypes.create_string_buffer(self.unpacked_size)
libmpq.libmpq__file_read(self._archive._mpq, self.number,
data, ctypes.c_uint64(len(data)), None)
return data.raw
def __repr__(self):
return "%r[%i]" % (self._archive, self.number)
def __iter__(self, Reader=Reader):
return Reader(self)
class Archive(object):
def __init__(self, source, ctypes=ctypes, File=File, libmpq=libmpq):
self._source = source
if isinstance(source, File):
assert not source.encrypted
assert not source.compressed
assert not source.imploded
self.filename = source._archive.filename
offset = source._archive.offset + source.offset
else:
self.filename = source
offset = -1
self._mpq = ctypes.c_void_p()
libmpq.libmpq__archive_open(ctypes.byref(self._mpq), self.filename,
ctypes.c_uint64(offset))
self._opened = True
for field_name, field_type in [
("packed_size", ctypes.c_uint64),
("unpacked_size", ctypes.c_uint64),
("offset", ctypes.c_uint64),
("version", ctypes.c_uint32),
("files", ctypes.c_uint32),
]:
func = getattr(libmpq, "libmpq__archive_" + field_name)
data = field_type()
func(self._mpq, ctypes.byref(data))
setattr(self, field_name, data.value)
def __del__(self, libmpq=libmpq):
if getattr(self, "_opened", False):
libmpq.libmpq__archive_close(self._mpq)
def __len__(self):
return self.files
def __contains__(self, item, ctypes=ctypes, libmpq=libmpq):
if isinstance(item, str):
data = ctypes.c_uint32()
try:
libmpq.libmpq__file_number(self._mpq, ctypes.c_char_p(item),
ctypes.byref(data))
except IndexError:
return False
return True
return 0 <= item < self.files
def __getitem__(self, item, ctypes=ctypes, File=File, libmpq=libmpq):
if isinstance(item, str):
data = ctypes.c_int()
libmpq.libmpq__file_number(self._mpq, ctypes.c_char_p(item),
ctypes.byref(data))
item = data.value
else:
if not 0 <= item < self.files:
raise IndexError, "file not in archive"
return File(self, item)
def __repr__(self):
return "mpq.Archive(%r)" % self._source
# Remove clutter - everything except Error and Archive.
del os, check_error, ctypes, errors, File, libmpq, Reader
if __name__ == "__main__":
import sys, random
archive = Archive(sys.argv[1])
print repr(archive)
for k, v in archive.__dict__.iteritems():
#if k[0] == '_': continue
print " " * (4 - 1), k, v
assert '(listfile)' in archive
assert 0 in archive
assert len(archive) == archive.files
files = [x.strip() for x in archive['(listfile)']]
files.extend(xrange(archive.files))
for key in files: #sys.argv[2:] if sys.argv[2:] else xrange(archive.files):
file = archive[key]
print
print " " * (4 - 1), repr(file)
for k, v in file.__dict__.iteritems():
#if k[0] == '_': continue
print " " * (8 - 1), k, v
a = str(file)
b = iter(file).read()
reader = iter(file)
c = []
while True:
l = random.randrange(1, 10)
d = reader.read(l)
if not d: break
assert len(d) <= l
c.append(d)
c = "".join(c)
d = []
reader.seek(0)
for line in reader:
d.append(line)
d = "".join(d)
assert a == b == c == d, map(hash, [a,b,c,d])
assert len(a) == file.unpacked_size
repr(iter(file))
reader.seek(0)
a = reader.readlines()
reader.seek(0)
b = list(reader)
assert a == b