Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.
Zero Tolerance for Disrespect

Leaderboard

Popular Content

Showing content with the highest reputation since 09/02/2025 in Posts

  1. Author: Myro Scope: Educational & research-oriented reverse engineering Status: Ongoing research Introduction: This thread documents an ongoing technical research project focused on analyzing the MPK container system used by Where Winds Meet (WWM). The goal is to understand the structure, behavior, and data flow of the game’s asset containers from a reverse-engineering and archival perspective, strictly for educational and analytical purposes. No proprietary assets, binaries, or tools will be distributed as part of this work. 1. Patch*#.mpk vs Resource*#.mpk — Structural Similarity, Semantic Differences At a container level, Patch#.mpk* and Resource#.mpk* share the same base format: Indexed via mpkinfo / mpkdb Entries contain: FileID Size Offset MpkIndex Use the same compression stack: LZ4 / ZSTD / LZMA EZST (AES-encrypted) However, despite this structural similarity, their extraction semantics differ significantly. 2. Patch*#.mpk — Partial Transparency, Direct Asset Access Patch MPKs behave primarily as delta / override containers: Assets retain near-original offsets Internal file structures remain largely recognizable Minimal indirection compared to Resource MPKs As a result: ~99% of audio assets can be recovered successfully A subset of Lua scripts becomes readable after decompression Non-audio assets (including some images) are present and partially accessible Testing on Patch3100.mpk confirmed that Patch archives are not limited to sound assets. Conclusion: Patch MPKs prioritize update efficiency and fast access, with limited transformation of payload data. 3. Resource*#.mpk — Indirection and Shared Data Resource MPKs represent the primary asset pool and introduce several additional complexities: The Size field often represents a logical or expanded size, not the physically stored payload Naïve extraction pipelines tend to: materialize padding and alignment blocks duplicate shared data blobs inflate archive size artificially (e.g. ~2 GB → tens of GB) This behavior explains why Resource MPKs appear far more “opaque” when extracted without validation. Important observations: Fixed headers such as 02 02 02 01 … frequently represent logical structures (e.g. texture containers with multiple mip blocks) Headers of the form size (4 bytes) + size × 20 bytes often describe lookup tables, not standalone assets Many assets are shared, aliased, or referenced indirectly Conclusion: While Patch and Resource MPKs share the same container format, they do not share the same extraction semantics. Resource MPKs require strict validation, deduplication, and asset-type verification to avoid false positives. 4. Audio Extraction & Tooling Initial testing with Ravioli Game Tools proved sub-optimal for this pipeline: Inconsistent parsing of Patch audio assets Unreliable WAV output in multiple cases Switching to vgmstream yielded significantly better results: Correct parsing of recovered audio data Clean, fully functional WAV output Proper handling of codec structures Current result: Audio extraction and conversion are fully verified and stable. 5. Resource.mpk Extraction – Current Progress Testing on Resources49.mpk (~740.9 MB) produced the following results: Successfully extracted: Audio assets → converted to valid .wav files Over 8,500 audio files identified in a single Resource MPK Video files (.mp4) → fully playable Lua scripts (.lua) → extracted but still encrypted / obfuscated Unresolved: Files detected as images (.png, .jpg, .bmp) Headers contain the string “messiah” Strongly suggests custom packing, encryption, or misclassification Currently not valid image data despite file extensions 6. Current Status ✔️All Patch*#.mpk, Resource*#.mpk, and lt*.mpk archives can be unpacked ✔ Audio assets fully recovered and validated ✔ MP4 video assets fully playable ✔ Lua scripts extracted but not yet readable 7. Next Steps Ongoing research will focus on: Reversing additional transformation layers in Resource*#.mpk Identifying: secondary encryption stages compression chaining block or stream reordering Investigating the custom image container format Further analysis of Lua encryption / obfuscation Automating Patch vs Resource handling as two distinct pipelines Notes on Tooling & Distribution All tools used in this project are: developed entirely from scratch created specifically for WWM research used strictly for educational purposes At this stage: no tools, binaries, or scripts will be released no proprietary assets will be redistributed Closing This thread is intended solely as a technical research and documentation log, not as a release, redistribution, or exploitation guide. In accordance with applicable intellectual property laws and forum policies, no tools, binaries, scripts, or extracted assets will be posted or shared, either publicly or privately. All game data, assets, file formats, and related materials discussed here remain the exclusive proprietary property of NetEase and the developers of Where Winds Meet. Any references to assets or file structures are made strictly for educational, analytical, and research purposes, with no intent to enable misuse, circumvention, or redistribution of protected content. Should any concerns arise regarding compliance or scope, I am fully open to cooperating with forum moderation and adjusting the visibility or content of this thread accordingly. Thank you for your understanding and for supporting responsible technical research. — Myro Below are a few illustrative screenshots and log excerpts from the current stage of the research, provided solely to contextualize the findings outlined above.
  2. We are currently testing whether we can retrieve character IDs from the database and read all related data
  3. Here is experimental version of dump tool for full version of Battlefield 6. (attached in the end of this post) For almost a whole year now since beta versions it was possible to use my set of tools to get ANY files from it, be that beta or full version. The only problem was "update" folder that was not supported as it is. To get it dumped, you had to move files from update folder to data folder. Each subfolder inside "update" has "data" inside, and you have to move contents to main "data" folder. It does not overlap and work as intended. Now i made this new version which must scan update folder and add data from it. Important change of .INI file is that now game path must NOT include "data" in the end: C:\games\bf6 D:\dump all After dumping, you can use same set of tools from here: bf6_update.7z
  4. 5 points
    I have released an early version of the tool that can do just meshes with their material names/skeleton:
  5. I Finally got materials and textures to load dynamically, so far only works on Conker will have to work in some tweaks to support other models
  6. i took a look at the .CB file and managed to crack it. 1. ENC0 / ENC2 are not encryption ENC is short for *encoding*, and the digit is the method number. *ENC0 — stored, no compression.** The CLSS blob follows the 8-byte header verbatim. That is exactly why CLSS / CTRFImageBuffer / IBUF were readable in a hex editor in the first place. The LZSS chunks live *inside* that blob. Every image resource in SSYF.CB is ENC0. *ENC2 — the whole record is LZSS-compressed.** Same bitstream as below, but with no 4-byte size prefix; the decompressed size is the resource size already in the TOC. Only the 20 .SET files use it. 2. The compression Chunk layout "LZSS" | u32 chunk_size | u32 decompressed_size | bitstream - Bits are read LSB-first within each byte — bit 0, then bit 1, … bit 7. - Multi-bit fields are assembled MSB-first — the first bit read is the field's most significant bit. Grammar. - flag bit 1 → literal: the next 8 bits are emitted directly. - flag bit 0 → match: 12-bit ring position, then 4-bit length, length = field + 2 (so 2..17 bytes). Window. - A 4096-byte ring buffer, initialised to 0x00, write pointer starting at 0. - pos is a 1-based ring index, so the copy source is ring[(pos - 1 + i) & 0xFFF]. pos == 0 never appears in a real token. - Every copied byte is written back into the ring at the write pointer, as usual. - The stream ends as soon as the declared byte count is produced. There is no end marker, and up to 2 bytes of zero padding follow. int bitpos = 0; int getbit (const u8 *s) { int b = (s[bitpos>>3] >> (bitpos&7)) & 1; bitpos++; return b; } u32 getbits(const u8 *s, int n) { u32 v = 0; while (n--) v = (v<<1) | getbit(s); return v; } u8 ring[4096] = { 0 }; u32 r = 0, o = 0; while (o < decompressed_size) { if (getbit(src)) { /* 1 = literal */ u8 c = getbits(src, 8); out[o++] = c; ring[r] = c; r = (r + 1) & 0xFFF; } else { /* 0 = match */ u32 pos = getbits(src, 12); /* 1-based ring index */ u32 len = getbits(src, 4) + 2; /* 2..17 */ u32 s = (pos - 1) & 0xFFF; for (u32 i = 0; i < len; i++) { u8 c = ring[(s + i) & 0xFFF]; out[o++] = c; ring[r] = c; r = (r + 1) & 0xFFF; } } } One chunk decompresses to at most 0x20000 bytes. Bigger images are split across consecutive LZSS chunks that concatenate to exactly width * height * 2. 3. The .dds files — CTRFImageBuffer "CLSS" | u32 len | class name, NUL-terminated ("CTRFImageBuffer") "IBUF" | u32 size | u32 (0) | u16 width | u16 height | u16 pitch (= width*2) | u16 planes (1) | u32 flags (0x00100000) | u32 mask A | u32 mask R | u32 mask G | u32 mask B | u8 bits A, R, G, B (e.g. 0, 5, 6, 5) | u8 top bit index A, R, G, B (e.g. 0, 15, 10, 4) then 1..n LZSS chunksThe pixel data is a plain linear raster 4. The .SET files, and exact frame reassembly Once decompressed, each .SET is a serialised CTRFDataSet that names the textures for a scene and gives the blit rectangles — so reassembly is read from the data. "CLSS" | u32 len | "CTRFDataSet\0" | u32 nrec per record: FF FF FF FF | u32 id | u16 namelen | name | payload CTRFTexture u32 | u32 count | count x NUL-terminated .dds names CTRFPictures u32 | u32 npics npics x ( u16 (0x10) | u16 npieces | u16 W | u16 H | u16 ox | u16 oy npieces x ( u32 texture index u16 sx0 sy0 sx1 sy1 <- inclusive source rect u16 dx0 dy0 dx1 dy1 )) <- inclusive dest rect npics x NUL-terminated picture name <- names come after ALL pictures u32Note that the picture names come after all the pictures, The typical scene is 640x480 built from three pieces: 512x480 from the _00 texture, then the _01 texture folded in half to supply the right-hand 128x480 strip. tex0 src (0,0)-(511,479) -> dst (0,0)-(511,479) tex1 src (0,0)-(127,255) -> dst (512,0)-(639,255) tex1 src (128,0)-(255,223) -> dst (512,256)-(639,479)A few sets sSYf_11) store frames at half vertical resolution and give a destination rect twice as tall — i.e. the game line-doubles them. Other record types are present CTRFContainer, CTRFClipperBuilder, CTRFPictureDraw, and TEXT / PICT / ANIM / LIPS / CLIP sections), but none are needed for images. Script attached: kitae_cb.py python kitae_cb.py .CB FILE -o extracted --assemble python kitae_cb.py .DDS FILE -o extracted # loose CLSS/IBUF file kitae_cb.py
  7. The attached script will dump everything that is inside of the .sprbin files. This includes the FSB files. I am cheating a little bit as I am using vgmstream-cli to do the heavy lifting for me. The FSB files are still available raw. Hope you will excuse me. 🥺 python .\SPRBIN_Extractor.py "path\to\folder\with\sprbin\files" "path\to\export\folder"Full list of resources this is currently extracting: Audio: Raw FSB files WAV converted through embedded vgmstream-cli Localization: CSV files containing game text Palettes: RGBA palette data PNG palette overview CSV for individual palette colour values Tables: Symbols: Named IDs used by the SPRBIN script Frames: Main sprite-frame records and source image paths Frames Extra: Additional values attached to individual frames Frame Placement: Objects or sprite positions associated with frames States: Animation or behavior-state records State Strings: Strings inside of compiled state data Pairs: Pairs of unidentified values stored in the frame and state data Palette Records: Details about embedded colour palettes and the images that use them Dependencies: External asset paths referenced by the SPRBIN SPRBIN_Extractor.7z
  8. Hello, this is a proprietary format from Ubisoft. After long months, I made an tool to handle this format. Check this out: Sources: https://github.com/OAleex/Ipu-Codec https://github.com/OAleex/Ubisoft-Int Ipu-Codec-v1.0.0-win-release.zip Ubisoft-Int-v1.0.0-win-release.zip
  9. Apparently there is a bug with Default Berri's hair Fur Shells are currently merging her Hair and Body material, due to an oversight in how the shells are drawn, getting a fix done now EDIT Here's the updated script RBMimport_12.py
  10. Here is the newest version most animations should work, I haven't tested everything yet added a search bar to make it easier to find assets you have loaded I tried to speed up the animation loading, but I don't think there is a real way to do it at this moment unless I worked on the memory stuff, right now its decrypting each frame, then keyframing it, so they can take about 3 to 4 minutes if you want to load another animation, its better to just refresh the scene, current bug is that the animation unloader has some memory cache'd for a few bones that I haven't been able to quash yet. sometimes the clear animation buttons works though I'm currently working on another Conker project, if that goes anywhere then I'll announce it here RBMimport_12.py
  11. Movement now works Here is the new script RBMimport_12.py Whats new Script will create custom materials based on shader, for example, Conker will now have proper material setups for his eyes and fur Fur support Animation support: currently only Conker's animations work from the Anims/Conker/default.rbm file to import an animation load model settings must look like this to work find animation rbm *Anims/Conker/Default.rbm* select the animation you want wait for it to process (Can be slow due to printing debug logs)
  12. got the poses to actually work, the blocker was a stupid piece of debug code I didn't notice was causing the orientation to flip when baking to the skeleton
  13. just to update everyone, I've gotten close, I had to scrap what I was doing multiple time, and decided the only way to get the animation to properly import is if I mirrored the stack building exactly, which I've seemingly accomplished, now the new issue is, I need to fix the skeleton's orientation upon import, because even though the animation pose imports, Conker looks dead this animation is the stance clip, used for his idle animation as you can see, once I fix the bind pose on the imported models, it should allow for the animation to be positioned correctly
  14. Let the SLPS in the same folder of out2.car and use this script below in quickbms selecting out2.car #Konjiki no Gashbell extractor by Rabatini open FDSE "SLPS_254.40" 1 get ARCHIVE_SIZE asize 0 get SLPS_SIZE asize 1 set BASE_LSN long 311 set VADDR_BASE long 0x247A80 set FILE_BASE long 0x148A80 set SCAN_START long 0x001000 math SCAN_END = SLPS_SIZE math SCAN_END - 0x1c set FOUND long 0 for POS = SCAN_START < SCAN_END goto POS 1 get NAME_PTR long 1 get TAG long 1 get LSN long 1 get SECTORS long 1 get ALLOC long 1 get SIZE long 1 get FLAGS long 1 if TAG == 0xFFFFFFFE math EXPECT = SECTORS math EXPECT * 0x800 if EXPECT == ALLOC if SIZE > 0 if SIZE <= ALLOC math OFFSET = LSN math OFFSET - BASE_LSN if OFFSET >= 0 math OFFSET * 0x800 math END_OFF = OFFSET math END_OFF + SIZE if END_OFF <= ARCHIVE_SIZE set DUP long 0 for J = 0 < FOUND getarray OLDLSN 0 J if OLDLSN == LSN set DUP long 1 break endif next J if DUP == 0 putarray 0 FOUND LSN math FOUND + 1 string NAME p= "files/%05d_%08x_%08x.bin" FOUND LSN SIZE # tenta resolver o nome pelo ponteiro da entrada math NAME_OFF = NAME_PTR math NAME_OFF - VADDR_BASE math NAME_OFF + FILE_BASE if NAME_OFF >= 0 if NAME_OFF < SLPS_SIZE goto NAME_OFF 1 getct TMP string 0x00 1 if TMP != "" string NAME = TMP endif endif endif log NAME OFFSET SIZE 0 endif endif endif endif endif endif endif # o for adiciona +1 no next, então aqui somamos +3 = passo real de 4 bytes math POS + 3 next POS Konjiki no Gashbell extractor by Rabatini.zip
  15. Hey there people! I've been lurking these forums for years now, Zenhax and Xentax as well, but haven't shared my tools (mainly because there were already working solutions from other people). This whole community is about sharing your knowledge and tools (and I know some people who have tools for other games, but won't share it with the community). Because I've just created a working solution I'd thought it would be best to share it with you guys. This would be my first post here, but don't let that distract you 🙂 HOW IT WORKS: 1. First you need to open your GMAIL account and open a Google Colab page ( https://colab.research.google.com/ ). 2. Click on the "New Notebook" option. 3. You'll see a folder that contains files, click on it! You'll have to wait a few seconds before it connects to the server. 4. Once you see the file structure (like the "sample_data" folder), drag and upload your original "gameresources_patch1_pc.resources" and your modified "strings" file there. 5. If it's done, then on the top you can see a console with a play button. Insert the whole script I've sent you, then press the Play button. 6. After a few seconds the console / log on the bottom should say that it's finished, and on the left you'll see a file called "NEW_gameresources_patch1_pc.resources". 7. Download that file and insert it into your game folder, renaming and replacing the original one (make sure you create a backup of it). 8. Run the game and it should work with your new strings. EDIT: My script targets the English language files and replaces the strings there. If you want to replace another language's files (maybe because of the fonts), you can update the script's eb value. EN_US (original): eb = 0x3D858 AR_SA: eb = 0x3D8E8 DE_DE: eb = 0x3DA98 ES_ES: eb = 0x3DB28 ES_MX: eb = 0x3DD68 FR_FR: eb = 0x3D978 IT_IT: eb = 0x3DA08 JA_JP: eb = 0x3DCD8 KO_KR: eb = 0x3DFA8 PL_PL: eb = 0x3DC48 PT_BR: eb = 0x3DDF8 RU_RU: eb = 0x3DBB8 ZH_CN: eb = 0x3DF18 ZH_TW: eb = 0x3DE88 Have fun! EDIT 2: I've updated my script, so it will automatically download the file with the correct name once it's done patching it, and also I've created a patcher for the PS5 version (since the original tool was only working for the PC version). Note that the entries differ for the PS5 version, so you can't use the above "eb" values for it! script_ps5.py script_pc.py
  16. Modding tools in progress (details in discord, forum thread will be created later). The first ever custom model in DS2. Extracted from the game, modified, and put back into it.
  17. I've updated my browser to include ChaCha20 stuff by Lazorr. Seems to work fine, but i guess once he updates his gui (currently it's even worse than this here :P), mine won't be needed anymore. Let's GO!!! 😄 Crimson Browser3.zip
  18. We are currently rewriting the code to support all animations.
  19. I've been so busy at work lately, but here is the version with fixed material batching RBMimport_noAnimation5.py
  20. Here is an updated version of the script What Changed: Added shader type detection Specular textures will now correctly pipe into the specular node Textures with a Cutout Alpha now correctly pipe into the alpha channel Fur is currently being worked on Added more attributes to the model Vertex Color is now supported Fur Length is now being collected (not fully implemented yet) Fixed an issue where some models never importing textures or materials I'll also update the original script post EDIT I'll be updating it again soon, appears some models have separate specular textures rather than them just deriving from the alpha, mostly the Barn_outside models RBMimport_noAnimation2.py
  21. I'm trying my best to make it load somehow
  22. I just figured out how to load external files like materials, textures. But absolute path must be set. I also noticed that *.entity is invoked by skeleton if there's any. External dds loading. But there is still one big issue. How are meshes handled. I still didn't figure out how indices reset. Holy sh!t it automatically converts textures to dds in cooperation with my script for textures
  23. Inspecting the Pet_Snake.bfz file shows that it indeed is a protected ZIP file with legacy ZipCrypto. The game executable is protected by Themida (😒) so I had to dump the running process to perform some analysis. The ZIP password is derived from the archive's resource path. The loader normalizes the separators, gets rid of the filename, takes the final directory component, and finally converts it all to uppercase. The string is then ran through an embedded lookup table and finally the results are all concatenated resulting in the valid password for this particular BFP file. Here is a script I wrote that will automatically generate the proper ZIP password for the given BFP file: TABLES = [ "as89f7d6af98e7f6a9s87f6as98f76asdf8yasuefyae8f7as6ef9ase87fa6se9", "alkjdfLKDFJeofias4894ewfadfklDFJfsafjlasff89a4fhJLKDSfHdf98daf9s", "afoiefajsfiasdf87ysda987dsfvhsdkvhs8dr7vhsdkfghsie4g8hsdfukzDFDf", "faklsjdfiod9f8asdfjKLDFjds9f8jasdklfjsdf9asd8fuseijkasdkHDFKJDf8", "dflkjasdf98asfuyaiufhaos8efhLHFDJSFhasod8fsdfkLDfd9f8aslkejfDLkf", "dkfjapsdoifjas9d8fajsdfiashdJKFSHdfdfaskdljf9sd8fasd89f7asieufa9", ] def bfz_password(package_path): path = package_path.encode("ascii") return "".join( TABLES[i % 6][path[i % len(path)] % 64] for i in range(64) ) def reconstruct_bfz_path(resource_path: str) -> str: normalized_path = resource_path.replace("\\", "/") separator_index = normalized_path.rfind("/") resource_directory = normalized_path[:separator_index] directory_separator = resource_directory.rfind("/") archive_name = resource_directory[directory_separator + 1:] return f"{resource_directory}/{archive_name}.bfz" def derive_bfz_kdf_input(resource_path: str) -> str: archive_path = reconstruct_bfz_path(resource_path) return archive_path.upper() if __name__ == "__main__": resource = "<FILENAME>" logical_archive_path = reconstruct_bfz_path(resource) password_generator_input = derive_bfz_kdf_input(resource) encrypted_password = bfz_password(password_generator_input) print(f"Resource path: {resource}") print(f"Logical archive path: {logical_archive_path}") print(f"KDF input: {password_generator_input}") print(f"Encrypted password: {encrypted_password}") I am taking the Pet_Snake.bfz file as example and I have opened in my tool. You can also open it in any other tool like 7zip, NotePad++, etc... as long as you can get the names of the files inside of the ZIP archive. You simply take any of the names, in this case we take Models/Characters/Pet_Snake/common/pis-basic-jump.face, and paste it in the <FILENAME> placeholder inside of the python script and run it. Resource path: Models/Characters/Pet_Snake/common/pis-basic-jump.face Logical archive path: Models/Characters/Pet_Snake/common/common.bfz KDF input: MODELS/CHARACTERS/PET_SNAKE/COMMON/COMMON.BFZ Encrypted password: 7aejsjajsauk94fjf8afasf9sefskd7f8aDj6fdsud8Lf8ya7odskos8flhps9sdThe encrypted password can then be used as password to extract the data from the ZIP file. I did not yet take a look at the PKN files you've supplied. I am planning on doing this soon.
  24. Working on it... But struggling with decompression via noesis. You need to use BMS first to decompress *.XMD. Or maybe i'll figure out. EDiT: Figured out. Now you don't need to decompress model... Here we go... # Script by h3x3r from inc_noesis import * import noesis import rapi import os def registerNoesisTypes(): handle = noesis.register("Deadly Premonition - XMD Mesh", ".xmd") noesis.setHandlerTypeCheck(handle, noepyCheckType) noesis.setHandlerLoadModel(handle, noepyLoadModel) noesis.logPopup() return 1 def noepyCheckType(data): bs = NoeBitStream(data) bs.read(8) CSize = bs.readUInt() Size = bs.readUInt() Buffer = bs.read(CSize) data = rapi.decompInflate(Buffer,Size) bs = NoeBitStream(data) if len(data) < 20: return 0 if bs.readUInt() != 0x33444D58: return 0 return 1 def noepyLoadModel(data, mdlList): bs = NoeBitStream(data) bs.read(8) CSize = bs.readUInt() Size = bs.readUInt() Buffer = bs.read(CSize) data = rapi.decompInflate(Buffer,Size) bs = NoeBitStream(data) baseName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getInputName())) ctx = rapi.rpgCreateContext() Underline = "_" # Main Info Sign = bs.read(4) ResourceSize = bs.readUInt() TotalIndexCount = bs.readUInt() TotalElementCount = bs.readUInt() Unknown_2 = bs.readUInt() Reserved0 = bs.read(20) Unknown_3 = bs.readUShort() BoneCount = bs.readUShort() ShapeCount = bs.readUInt() Unknown_4 = bs.readUInt() Unknown_5 = bs.readUByte() Unknown_6 = bs.readUByte() Unknown_7 = bs.readUByte() Unknown_8 = bs.readUByte() Unknown_9 = bs.readUByte() ElementStride = bs.readUByte() NormalSkinStride = bs.readUByte() Unknown_12 = bs.readUByte() Reserved1 = bs.readUInt() BBoxMin = bs.read(12) BBoxMax = bs.read(12) Unknown_13 = bs.readUShort() Unknown_14_Count = bs.readUShort() Unknown_15 = bs.readUInt() Unknown_16 = bs.readUInt() MaterialDefOffset = bs.readUInt() BoneDefOffset = bs.readUInt() ShapeDefOffset = bs.readUInt() Unknown_17 = bs.readUInt() Unknown_18 = bs.readUInt() UnknownDefOffset = bs.readUInt() Reserved2 = bs.read(16) IndexBufferBaseOffset = bs.readUInt() ElementBufferBaseOffset = bs.readUInt() NormalSkinBufferBaseOffset = bs.readUInt() Reserved3 = bs.read(16) Unknown_14_Offset = bs.readUInt() print("Element Stride >",ElementStride,"NormalSkin Stride >",NormalSkinStride) # Material Info bs.seek(MaterialDefOffset, NOESEEK_ABS) MaterialName = bs.readString() rapi.rpgSetMaterial(MaterialName) # Shape Info bs.seek(ShapeDefOffset, NOESEEK_ABS) for i in range(0, ShapeCount): StrPos = bs.tell() ShapeName = bs.readString() bs.seek(StrPos, NOESEEK_ABS) bs.read(16) Unknown_0 = bs.readShort() BoneId = bs.readShort() Unknown_2 = bs.readUInt() Unknown_3 = bs.readUInt() BBoxMin = bs.read(12) BBoxMax = bs.read(12) IndexCount = bs.readUInt() ElementCount = bs.readUInt() IndexOffset = bs.readUInt() * 2 ElementOffset = bs.readUInt() Unknown_4 = bs.readUInt() Reserved = bs.read(8) cPos = bs.tell() bs.seek(ElementBufferBaseOffset + (ElementOffset * ElementStride), NOESEEK_ABS) ElementBuffer = bs.read(ElementCount * ElementStride) if ElementStride == 20: rapi.rpgBindPositionBufferOfs(ElementBuffer, noesis.RPGEODATA_HALFFLOAT, 20, 0) rapi.rpgBindUV1BufferOfs(ElementBuffer, noesis.RPGEODATA_HALFFLOAT, 20, 8) elif ElementStride == 24: rapi.rpgBindPositionBufferOfs(ElementBuffer, noesis.RPGEODATA_FLOAT, 24, 0) rapi.rpgBindUV1BufferOfs(ElementBuffer, noesis.RPGEODATA_HALFFLOAT, 24, 12) bs.seek(NormalSkinBufferBaseOffset + (ElementOffset * NormalSkinStride), NOESEEK_ABS) NormalSkinBuffer = bs.read(ElementCount * NormalSkinStride) if NormalSkinStride == 12: rapi.rpgBindNormalBufferOfs(NormalSkinBuffer, noesis.RPGEODATA_HALFFLOAT, 12, 0) rapi.rpgBindBoneWeightBufferOfs(NormalSkinBuffer, noesis.RPGEODATA_HALFFLOAT, 12, 6, 3) elif NormalSkinStride == 16: rapi.rpgBindNormalBufferOfs(NormalSkinBuffer, noesis.RPGEODATA_HALFFLOAT, 16, 0) rapi.rpgBindBoneWeightBufferOfs(NormalSkinBuffer, noesis.RPGEODATA_HALFFLOAT, 16, 8, 3) bs.seek(IndexBufferBaseOffset + IndexOffset, NOESEEK_ABS) IndexBuffer = bs.read(IndexCount * 2) rapi.rpgSetStripEnder(0xFFFF) rapi.rpgSetName(ShapeName) rapi.rpgCommitTriangles(IndexBuffer, noesis.RPGEODATA_USHORT, IndexCount, noesis.RPGEO_TRIANGLE_STRIP) bs.seek(cPos, NOESEEK_ABS) mdl = rapi.rpgConstructModel() mdlList.append(mdl) return 1No skin/bones/skeleton. Could be done later...
  25. I guess now that I'm actually getting some progress going, the next project I'm working on is an actual game loader, it won't be in blender. Blender is just a debug space for it. so technically what it will be is like those Mario 64 loader where you have to provide your own game root folder, but once loaded, it will allow you to mod the game, and stuff like that. Still a lot of functions I need to go through, but its getting there, hopefully everything goes alright
  26. There are at least two types of i3d file formats, used within the .i3d files used in ape escape 3 and Rule of Rose uses .i3d files in .mdl files. I3D_BIN: Mesh ✔️ Bones ✔️ Skin ❌ I3D_I3M: Animation ❌ Tools: https://github.com/Durik256/Noesis-Plugins/blob/master/fmt_i3dg.py - Supports meshes. fmt_RuleOfRose_PS2__i3d.zip - Supports bones (made by Bigchillghost from xentax, reuploaded into reshax for quicker accessibility)
  27. New Version of TASM 1+2 Tools Audio is now sorted/named Also sorted into languages.
  28. good news is I now got animation poses showing correctly Bad news, I need to fix the bind pose for the imported armature
  29. I got the initial pose to show decent, still some areas where the rotation isn't exactly right, mostly the limbs,
  30. Here you go - plugin for Blender 5.0 Imports meshes, skeletons, animations and textures Some animation files may fail to import (could not figure it out) io_scene_until_dawn_demo.zip
  31. Thank you, with this I was able to put the image ImageHeat (see first image) and export it as a .png, and after modifying the .atlas to read the .png, I was able to lead the animation in my Spine Viewer However, he looks weird, with most of the problems around the edges (like his collar or his eyes), which may have something to do with the outline that I think is in "rim-DEFAULT." However, I can't seem to figure out a way to export the texture from rim properly. kermit.zip
  32. Right, sorry, I didn't notice that you read them as half floats. Here is the updated plugin. Note that Noesis will hide parts of the mesh in the preview unless you change the blend mode from "Alpha + alpha test" to "None" with F11. fmt_juiced2_d9m.py
  33. I've fixed pngs and added reimport (only smaller or same size files without compression etc. for now) and it surprisingly worked first try 😄 Will update later.
  34. Based on MrIkso’s research, I had Codex slap together a basic browser that can display various file types and includes a few extra bonus features. It also properly decompresses LZ4 files, but don’t get your hopes up when you see the crimson_chacha20_key.hex file... that’s only useful if someone manages to extract the actual key from the executable or from memory. I’ve also included vgmstream-win in the folder so you can preview the game’s audio files, which was my main goal anyway 😛 Just adjust ARCHIVES_PATH = r"D:\SteamLibrary\steamapps\common\Crimson Desert" in the Python file so it points to your game directory and the tool can find the archives. It may look like the program is hanging on startup, but it’s actually busy parsing everything, including its best guesses at the folder structure. Give it a minute or so... Run it with: python crimson_browser.py You might need to install a few dependencies first via pip. Crimson Browser.zip
  35. Phew, first of all, i'm still impressed how Chipicao managed this Format back then, shoutout to him i've went through all games i could find that are using the "GEM Graphics Engine Milestone" and tried to restructure some of the skips and guesses in Chipicao's max script \ tried to write a newer version - failsave for each game the reason why the script does crash on sebastien loeb rally is because they rebuilt these bin files roughly 3 times, sadly there is no real identifier to tell which game the bin file belongs to gen 1 (SBK09, SBK10, Superstars V8, Superstars Next Challenge, WRC1) - which had their vertex buffer stored one by one (vert - normals - uvs - index - etc) gen 2 (SBK11, SBK Generations, MUD, MXGP 1, MotoGP13, WRC2, WRC3, WRC4, WRC Powerslide) - started to combine the vertexbuffers on stride with multiple fvfcode / types these games also came with a seperate *.RES file which sometimes stored either just strings, or packed (uncompressed) DDS textures, Chipicaos script was able to extract them so i've moved that chunk over gen 3 (MotoGP14, MotoGP15, MotoGP16(ValentinoRossi), MotoGP17, Ducati 90th Anniversary, MXGP 2, RIDE 1, RIDE 2, Sebastien Loeb Rally EVO) - dropped the .RES files, but included the stringlist to the .BIN file packed under a new header hash 9241a9d5 CLSID_DIRECTSTREAMINGOBJECT these GEM files are split into a ton of chunks, starting usually with 5b2a 5b42 5b30 - then another 2byte type - then the Hash which kind it is - i've found one MotoGP13.PDB file which named some of these hashes (yet i cant tell which algo it is using) - each game also varies between having a hash bc258a42 CLSID_NAMEDOBJECT in between blocks, it really is chaotic (yet structurized...) i havent looked much into the track files yet, if someone else wants to continue attempting this, feel free to go through this chunky and messy code 😅 there is a lot of offset jumping required - so it first starts with texture count, material count, meshcount and node/bone count - the meshchunk jumps back and reads the material block at offset x etc. - the bones offset jumps are just mental i've ignored the texture and material setup for now and focused on getting at least the meshes and bones however, this thing is so chaotic, i got lost at jumping down to the indexbuffer which then skips the unneeded vertices, thats why it will load the entire vertexbuffer per object, so as for now, use the removeunusedvertices.ms script in there 😓 the bone orientation is different to the meshes - which could be fixed in the script - or just rotate the rootbone to fit the mesh orientation - since boneweights are yet not applied aswell (loading time on these vertexbuffer is long enough already) - some of these bones or dummies are required to place the meshes in the correct position / orientation long story short, these are 24 standalone max scripts to import these files, a script to get rid of dead vertices and a color map for hexworkshop to spot these pointers have fun Milestone_Gem.7z
  36. Here's a quick little texture extractor for blender import a map, or model open, or paste the script in the script editor edit the output path to where you want them to go press run script all textures currently in your scene are exported refresh the scene if you want to keep the textures tidy you will have some missing textures, because I forgot to reimplement the extra textures stored inside the texture handles, it will get reimplemented soon batch_imgextract.py
  37. Try the attached script for XMF files. I also adjusted the XCF script to read the triangles strips a bit differently, though both mesh types still have some random edges. There were also some DX textures in the level archive, so I added support for them to the XTF script. fmt_fight_club_xcf.py fmt_fight_club_xmf.py fmt_fight_club_xtf.py
  38. The attached Noesis plugin should work on the .xtf textures. The colours might still need some tweaking, as they look a bit greyed out. The section after the header might be a colour palette, though I don't know how to parse it. fmt_fight_club_xtf.py
  39. HAPPY NEW YEARS, and to you Uber, thanks for the script man. HAPPY HOLIDAYS!
  40. This looks correct. The palette is RGB5551, but is swizzled with the same method as the image (not the standard PS2 palette shift). Patrick should be able to confirm if that can be added to ImageHeat as a palette swizzle option.
  41. I don't know if there are more models in that unpacked folder, you need to check that so examine each file there. Just remember that characters use shorts in vertices buffer, I think I saw other file with floats but maybe that file is not a character or maybe it is but with floats, I really don't know, lol. Here is the script if you want to test it: fmt_black_ps2_prototype_DB.py
  42. I've just released new version of ImageHeat 🙂 https://github.com/bartlomiejduda/ImageHeat/releases/tag/v0.39.1 Changelog: - Added new Nintendo Switch unswizzle modes (2_16 and 4_16) - Added support for PSP_DXT1/PSP_DXT3/PSP_DXT5/BGR5A3 pixel formats - Fixed issue with unswizzling 4-bit GameCube/WII textures - Added support for hex offsets (thanks to @MrIkso ) - Moved image rendering logic to new thread (thanks to @MrIkso ) - Added Ukrainian language (thanks to @MrIkso ) - Added support for LZ4 block decompression - Added Portuguese Brazillian language (thanks to @lobonintendista ) - Fixed ALPHA_16X decoding - Adjusted GRAY4/GRAY8 naming - Added support section in readme file
  43. Actually the LZSS provide above, is wrong, for the files. I did the reverse enginner of the algorithim, Try the tool, see if the image get right TenchuWoH_DeCompressor.zip
  44. So I was wrong, Conker's Eyes don't rely on a shader to make them look correct, the eyes have 3 UV channels for the Pupil, Highlight, and the Eye Lids. I just recently implemented the Multi UV Channel support
  45. Those BSTEX files are just containers for PS Vita GXT image files. Here's a file format https://rewiki.miraheze.org/wiki/GXT_Image If you remove manually 32 bytes from BSTEX file in hex editor and change file extension from BSTEX to GXT, you will be able to open them in Scarlet. Unfortunately PVRTII4BPP is not supported by Scarlet, so you will be able to convert only BC/DXT textures this way. While doing research on your samples, I discovered that ImageHeat had a bug while unswizzling 4bpp PS Vita textures. I fixed this bug in v0.26.3, so you can use this version (or newer) to properly view PVRTII4BPP textures:
  46. N64 logo and Rareware logo work aswell, forgot to test them

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.