mirror of
https://github.com/celisej567/mcpe.git
synced 2026-01-03 05:49:04 +03:00
* macOS Support & Cleanup * Fix malformed comments in build-wasm.bat * Emscripten Fixes * * Add shebang to the grabsounds.py script Since it was changed from rw- to rwx, I'll add the shebang so that it actually runs properly. * * Re-add the patch_data and readme files. * * Remove sound data. * Fix some more things. * Think it's ready to pull now... --------- Co-authored-by: BrentDaMage <BrentDaMage@users.noreply.github.com> Co-authored-by: iProgramInCpp <iprogramincpp@gmail.com>
153 lines
4.8 KiB
Python
Executable File
153 lines
4.8 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
# Minecraft PE Reverse Engineering Project
|
|
# Copyright (C) 2023 iProgramInCpp
|
|
# -----------------------------------------------
|
|
# This tool grabs the sound data from the .so file from the mcpe01_canada.apk. Offsets are hardcoded to that version, nothing else will work.
|
|
import sys
|
|
import os
|
|
import hashlib
|
|
|
|
# use memory efficient range always
|
|
merange = range
|
|
try:
|
|
merange = xrange # python 2
|
|
except NameError:
|
|
pass
|
|
|
|
# defines
|
|
pcm_addresses = [
|
|
('PCM_cloth1', 0x0014CFE8),
|
|
('PCM_cloth2', 0x00151614),
|
|
('PCM_cloth3', 0x00155C40),
|
|
('PCM_cloth4', 0x0015A26C),
|
|
('PCM_grass1', 0x0015E898),
|
|
('PCM_grass2', 0x001694EC),
|
|
('PCM_grass3', 0x00174140),
|
|
('PCM_grass4', 0x0017ED94),
|
|
('PCM_gravel1', 0x001899E8),
|
|
('PCM_gravel2', 0x0019463C),
|
|
('PCM_gravel3', 0x0019F290),
|
|
('PCM_gravel4', 0x001A9EE4),
|
|
('PCM_sand1', 0x001B4B38),
|
|
('PCM_sand2', 0x001BB6F4),
|
|
('PCM_sand3', 0x001C22B0),
|
|
('PCM_sand4', 0x001C8E6C),
|
|
('PCM_stone1', 0x001CFA28),
|
|
('PCM_stone2', 0x001DA67C),
|
|
('PCM_stone3', 0x001E52D0),
|
|
('PCM_stone4', 0x001EFF24),
|
|
('PCM_wood1', 0x001FAB78),
|
|
('PCM_wood2', 0x002057CC),
|
|
('PCM_wood3', 0x00210420),
|
|
('PCM_wood4', 0x0021B074),
|
|
('PCM_click', 0x00225CC8),
|
|
('PCM_explode', 0x00231D88),
|
|
('PCM_splash', 0x00243F18)
|
|
]
|
|
|
|
so_file_sha256 = '74b1d3b51a174c4dcaaa58d2bbdf7a4f4c9cfe5f2aeec4844427c2b8f1124343'
|
|
|
|
header_1 = '// Minecraft Pocket Edition Reverse Engineering Project\n// Copyright (C) 2011 Mojang Specifications.\n'
|
|
header_2 = '// Data extracted from libminecraftpe.so (mcpe01_canada.apk).\n\n'
|
|
|
|
def read_int_from_bytes(arr_bytes, offset):
|
|
return arr_bytes[offset] | arr_bytes[offset + 1] << 8 | arr_bytes[offset + 2] << 16 | arr_bytes[offset + 3] << 24
|
|
|
|
def read_short_from_bytes(arr_bytes, offset):
|
|
return arr_bytes[offset] | arr_bytes[offset + 1] << 8
|
|
|
|
def format_hex_short(short):
|
|
return "{:04x}".format(short)
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print('Usage:', sys.argv[0], '[libminecraftpe.so] (output dir)')
|
|
return
|
|
|
|
output_dir = ''
|
|
|
|
if len(sys.argv) > 2:
|
|
output_dir = sys.argv[2]
|
|
|
|
if len(output_dir) == 0:
|
|
output_dir = './sound_data/'
|
|
|
|
# append a slash to the file name, if it doesn't have one already
|
|
if output_dir[len(output_dir) - 1] != '/':
|
|
output_dir += '/'
|
|
|
|
if not os.path.exists(output_dir):
|
|
os.makedirs(output_dir)
|
|
|
|
bytes = []
|
|
|
|
# open the file
|
|
try:
|
|
with open(sys.argv[1],mode='rb') as sofile:
|
|
# read all bytes
|
|
bytes = sofile.read()
|
|
|
|
except FileNotFoundError:
|
|
print('ERROR: The file', sys.argv[1], 'was not found.')
|
|
return
|
|
|
|
# first off, hash the file to ensure it matches
|
|
src_sha256 = hashlib.sha256(bytes).hexdigest()
|
|
|
|
print('* Source file hash: ', src_sha256)
|
|
|
|
if src_sha256 != so_file_sha256:
|
|
print('ERROR: Source file does not match mcpe01_canada.apk\'s SO file. Please extract one from the aforementioned APK.')
|
|
return
|
|
|
|
print('* Extracting PCM data...')
|
|
|
|
include_all_str = '#pragma once\n\n' + header_1
|
|
include_all_str+= '\n// @NOTE: This is meant to be included in exactly 1 compile object/source file.\n\n' + header_2
|
|
|
|
for item in pcm_addresses:
|
|
include_all_str += '#include "' + item[0] + '.h"\n'
|
|
ostr = header_1 + header_2
|
|
|
|
channels = read_int_from_bytes(bytes, item[1] + 0)
|
|
data_length = read_int_from_bytes(bytes, item[1] + 12)
|
|
|
|
# @NOTE: All the PCM sound data is in `.data`. So there's no consts to be found.
|
|
|
|
ostr += 'PCMSoundHeader '+item[0]+' =\n{\n'
|
|
ostr += '\t' + str(channels) + ',\n'
|
|
ostr += '\t' + str(read_int_from_bytes(bytes, item[1] + 4)) + ',\n'
|
|
ostr += '\t' + str(read_int_from_bytes(bytes, item[1] + 8)) + ',\n'
|
|
ostr += '\t' + str(data_length)
|
|
ostr += '\n};\n\n'
|
|
|
|
data_length *= channels
|
|
|
|
ostr += 'uint16_t '+item[0]+'_data['+str(data_length)+'] =\n{'
|
|
|
|
for i in merange(data_length):
|
|
if i % 16 == 0:
|
|
ostr += '\n\t'
|
|
ostr += '0x'+format_hex_short(read_short_from_bytes(bytes, item[1] + 16 + i * 2)) + ','
|
|
|
|
ostr += '\n};\n'
|
|
|
|
filename = output_dir + item[0] + '.h'
|
|
with open(filename, 'w') as of:
|
|
of.write(ostr)
|
|
|
|
include_all_str += '\n\n'
|
|
|
|
for item in pcm_addresses:
|
|
include_all_str += 'SoundDesc SA_' + item[0][4:] + '(' + item[0] + ', ' + item[0] + '_data);\n'
|
|
|
|
with open(output_dir + 'sounds.h', 'w') as of:
|
|
of.write(include_all_str)
|
|
|
|
pass
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|