2015-06-04 16:30:23 -05:00
|
|
|
from panda3d.core import *
|
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
import argparse, struct
|
|
|
|
import sys, glob
|
|
|
|
import os
|
|
|
|
|
|
|
|
sys.path.append('nirai/src')
|
|
|
|
|
|
|
|
from niraitools import *
|
2015-06-04 16:30:23 -05:00
|
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('--compile-cxx', '-c', action='store_true',
|
2015-08-14 15:44:11 -05:00
|
|
|
help='Compile the CXX codes and generate stride.exe into built.')
|
2015-06-04 16:30:23 -05:00
|
|
|
parser.add_argument('--make-nri', '-n', action='store_true',
|
|
|
|
help='Generate stride NRI.')
|
2015-08-14 15:44:11 -05:00
|
|
|
parser.add_argument('--make-mfs', '-m', action='store_true',
|
|
|
|
help='Make multifiles')
|
2015-06-04 16:30:23 -05:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
if not os.path.exists('built'):
|
|
|
|
os.mkdir('built')
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
def niraicall_obfuscate(code):
|
|
|
|
# We'll obfuscate if len(code) % 4 == 0
|
|
|
|
# This way we make sure both obfuscated and non-obfuscated code work.
|
|
|
|
if len(code) % 4:
|
|
|
|
return False, None
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-08-16 21:32:55 -05:00
|
|
|
# Reverse
|
|
|
|
code = code[::-1]
|
|
|
|
|
2015-08-23 17:04:26 -05:00
|
|
|
# XOR
|
|
|
|
key = ['B', 'A', 'Q', 'J', 'R', 'P', 'Z', 'P', 'A', 'H', 'U', 'T']
|
|
|
|
output = []
|
|
|
|
|
|
|
|
for i in range(len(code)):
|
|
|
|
xor_num = ord(code[i]) ^ ord(key[i % len(key)])
|
|
|
|
output.append(chr(xor_num))
|
|
|
|
|
|
|
|
code = ''.join(output)
|
2015-08-16 21:32:55 -05:00
|
|
|
|
|
|
|
return True, code
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
niraimarshal.niraicall_obfuscate = niraicall_obfuscate
|
2015-06-04 16:30:23 -05:00
|
|
|
|
2015-09-06 17:01:10 -05:00
|
|
|
class StridePackager(NiraiPackager):
|
2015-08-16 11:29:30 -05:00
|
|
|
HEADER = 'TTSTRIDE'
|
2015-06-04 16:30:23 -05:00
|
|
|
BASEDIR = '..' + os.sep
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-09-06 17:01:10 -05:00
|
|
|
def __init__(self, outfile, configPath=None):
|
2015-06-04 16:30:23 -05:00
|
|
|
NiraiPackager.__init__(self, outfile)
|
|
|
|
self.__manglebase = self.get_mangle_base(self.BASEDIR)
|
2015-08-19 15:56:49 -05:00
|
|
|
self.add_panda3d_dirs()
|
|
|
|
self.add_default_lib()
|
2015-09-06 17:01:10 -05:00
|
|
|
self.globalConfigPath = configPath
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
def add_source_dir(self, dir):
|
|
|
|
self.add_directory(self.BASEDIR + dir, mangler=self.__mangler)
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
def add_data_file(self, file):
|
|
|
|
mb = self.get_mangle_base('data/')
|
|
|
|
self.add_file('data/%s.py' % file, mangler=lambda x: x[mb:])
|
2015-06-05 00:05:01 -05:00
|
|
|
|
|
|
|
def __mangler(self, name):
|
2015-06-04 16:30:23 -05:00
|
|
|
if name.endswith('AI') or name.endswith('UD') or name in ('ToontownAIRepository', 'ToontownUberRepository',
|
2015-08-14 15:44:11 -05:00
|
|
|
'ToontownInternalRepository', 'ServiceStart'):
|
2015-06-04 16:30:23 -05:00
|
|
|
if not 'NonRepeatableRandomSource' in name:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
return name[self.__manglebase:].strip('.')
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
def generate_niraidata(self):
|
|
|
|
print 'Generating niraidata'
|
2015-09-06 17:01:10 -05:00
|
|
|
if self.globalConfigPath is not None:
|
|
|
|
config = self.get_file_contents(self.globalConfigPath)
|
|
|
|
else:
|
|
|
|
config = self.get_file_contents('../dependencies/config/general.prc')
|
|
|
|
config += '\n\n' + self.get_file_contents('../dependencies/config/release/qa.prc')
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
config_iv = self.generate_key(16)
|
|
|
|
config_key = self.generate_key(16)
|
|
|
|
config = config_iv + config_key + aes.encrypt(config, config_key, config_iv)
|
2015-06-04 16:30:23 -05:00
|
|
|
niraidata = 'CONFIG = %r' % config
|
2015-08-14 15:44:11 -05:00
|
|
|
|
|
|
|
# DC
|
|
|
|
niraidata += '\nDC = %r' % self.get_file_contents('../dependencies/astron/dclass/stride.dc', True)
|
2015-06-04 16:30:23 -05:00
|
|
|
self.add_module('niraidata', niraidata, compile=True)
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
def process_modules(self):
|
2015-08-14 15:44:11 -05:00
|
|
|
# TODO: Compression
|
2015-06-04 16:30:23 -05:00
|
|
|
dg = Datagram()
|
2015-08-19 15:56:49 -05:00
|
|
|
dg.addUint32(len(self.modules))
|
2015-06-04 16:30:23 -05:00
|
|
|
for moduleName in self.modules:
|
|
|
|
data, size = self.modules[moduleName]
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
dg.addString(moduleName)
|
|
|
|
dg.addInt32(size)
|
|
|
|
dg.appendData(data)
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
data = dg.getMessage()
|
2015-08-14 15:44:11 -05:00
|
|
|
iv = self.generate_key(16)
|
|
|
|
key = self.generate_key(16)
|
|
|
|
fixed_key = ''.join(chr((i ^ (7 * i + 16)) % ((i + 5) * 3)) for i in xrange(16))
|
|
|
|
fixed_iv = ''.join(chr((i ^ (2 * i + 53)) % ((i + 9) * 6)) for i in xrange(16))
|
|
|
|
securekeyandiv = aes.encrypt(iv + key, fixed_key, fixed_iv)
|
|
|
|
return securekeyandiv + aes.encrypt(data, key, iv)
|
|
|
|
|
|
|
|
# Compile the engine
|
|
|
|
if args.compile_cxx:
|
2015-09-03 19:31:08 -05:00
|
|
|
compiler = NiraiCompiler('stride.exe', libs=set(glob.glob('libpandadna/libpandadna.dir/Release/*.obj')))
|
2015-08-14 15:44:11 -05:00
|
|
|
|
|
|
|
compiler.add_nirai_files()
|
|
|
|
compiler.add_source('src/stride.cxx')
|
|
|
|
|
|
|
|
compiler.run()
|
2015-06-05 18:21:47 -05:00
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
# Compile the game data
|
|
|
|
if args.make_nri:
|
|
|
|
pkg = StridePackager('built/TTSData.bin')
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
pkg.add_source_dir('otp')
|
|
|
|
pkg.add_source_dir('toontown')
|
|
|
|
|
|
|
|
pkg.add_data_file('NiraiStart')
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-06-04 16:30:23 -05:00
|
|
|
pkg.generate_niraidata()
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
pkg.write_out()
|
2015-06-05 00:05:01 -05:00
|
|
|
|
2015-08-14 15:44:11 -05:00
|
|
|
if args.make_mfs:
|
|
|
|
os.chdir('../resources')
|
|
|
|
cmd = ''
|
|
|
|
for phasenum in ['3', '3.5', '4', '5', '5.5', '6', '7', '8', '9', '10', '11', '12', '13']:
|
|
|
|
print 'phase_%s' % (phasenum)
|
|
|
|
cmd = 'multify -cf ../build/built/resources/default/phase_%s.mf phase_%s' % (phasenum, phasenum)
|
|
|
|
p = subprocess.Popen(cmd, stdout=sys.stdout, stderr=sys.stderr)
|
|
|
|
v = p.wait()
|
|
|
|
|
|
|
|
if v != 0:
|
|
|
|
print 'The following command returned non-zero value (%d): %s' % (v, cmd[:100] + '...')
|
|
|
|
sys.exit(1)
|