{"id":42557771,"url":"https://github.com/chipolux/disrev","last_synced_at":"2026-04-01T23:00:59.077Z","repository":{"id":61094533,"uuid":"548241767","full_name":"chipolux/disrev","owner":"chipolux","description":"Dishonored 2 Reverse Engineering","archived":false,"fork":false,"pushed_at":"2023-11-19T11:46:31.000Z","size":988,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-03-22T17:24:21.960Z","etag":null,"topics":["assets","dishonered-2","modding","reverse-engineering"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chipolux.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-10-09T06:59:24.000Z","updated_at":"2024-02-04T13:18:15.000Z","dependencies_parsed_at":"2023-01-22T00:01:58.796Z","dependency_job_id":null,"html_url":"https://github.com/chipolux/disrev","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chipolux/disrev","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipolux%2Fdisrev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipolux%2Fdisrev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipolux%2Fdisrev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipolux%2Fdisrev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chipolux","download_url":"https://codeload.github.com/chipolux/disrev/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chipolux%2Fdisrev/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assets","dishonered-2","modding","reverse-engineering"],"created_at":"2026-01-28T20:00:26.602Z","updated_at":"2026-04-01T23:00:59.059Z","avatar_url":"https://github.com/chipolux.png","language":"C++","funding_links":[],"categories":["Game \u0026 Studio Tools"],"sub_categories":["Arkane Studios"],"readme":"# Dishonored 2 Reverse Engineering\n\nDeconstructing the Dishonored 2 assets with the end goal of creating custom levels.\n\nAt this stage you can use the `resources.py` script to extract the assets from\nthe game data. It doesn't do anything automatically, but you can use the\n`ResourceContainer` class within to parse the indexes and then call the `.export()`\nmethod on the loaded `ResourceEntry` objects to export individual assets. See\nthe `test_export()` function for 90% of that.\n\n**Roadmap:**\n- [X] Extract 3D models, level definitions, and other assets.\n- [X] Modify plaintext assets and repack. (subtitles, etc.)\n- [ ] Interpret custom asset data formats. (bimage7, bwm, etc.)\n- [ ] Modify binary assets and repack. (move wall/table/chair or something)\n\nYou can find a list of all packed file extensions with some basic notes [here.](docs/dst-exts.txt)\n\nAnd a csv of Type, SrcExt, DstExt combos [here.](docs/type-src-dst-combos.csv)\n\nA lot of work was already done by the wonderful folks [in this thread!](https://forum.xentax.com/viewtopic.php?t=15518)\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003eInstallation Directory\u003c/h3\u003e\u003c/summary\u003e\n\nHere is an example installation directory:\n\n```\nDishonored2/\n└───base/\n    ├───cfg/\n    ├───pck/\n    ├───shaderCache/\n    ├───video/\n    ├───game1.index\n    ├───game1.resources\n    ├───game1_001.index\n    ├───game1_001.resources\n    ~~~~\n    ├───game1_005.index\n    ├───game1_005.resources\n    ├───game1_patch.index\n    ├───game1_patch.resources\n    ~~~~\n    ├───game4_patch.index\n    ├───game4_patch.resources\n    ├───master.index\n    ├───shared_2_3.sharedrsc\n    ~~~~\n```\n\nThe files in the `pck` and `video` directories seem to be sound effect, voice line,\nand video assets which would be dependent on localization so are likely delivered\nin separate per region depots. So we are mostly concerned with the `.index`,\n`.resources`, and `.sharedrsc` files.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003egameN Containers\u003c/h3\u003e\u003c/summary\u003e\n\nI'm not sure what the significance of each `gameN` group is, they seem to just\ncontain chunks of the game in an order that roughly matches a normal playthrough.\n\nI call these groups with matching `gameN` prefixes \"containers\".\n\nWithin each container it seems you can have up to 1000 patch levels, `_001` thru\n`_999` and a final `_patch` entry. In reality each container always has `_001`\nthru `_005` and a final `_patch`.\n\nEach level appears to supersede the previous levels. For example, all of the\nentries in `game1.index` are present in `game1_001.index` with only minor changes\nand a few additions.\n\nIt does seem like later patch levels can de-list entries. Leaving chunks of some\n`.resources` files orphaned.\n\nBut `.resources` files themselves never go unused! Later patch levels always\nreference data in the earlier `.resources`. Though an entry in a later patch level\ncan point the same \"destination\" asset to a different `.resources` file, this\nshould be obvious as a way to let devs bundle new versions of textures/models/etc.\nwithout breaking old builds or modifying files in place once they have been shipped.\n\nInterestingly there is nothing stored in the `game4` container!\n\nOh, and entries in an index never reference `.resources` in different container\naside from the special shared resource file.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003e.index Files\u003c/h3\u003e\u003c/summary\u003e\n\nEach `.index` file can be at most `uint32 - 32` bytes long.\n\nHere is a pseudo-code representation of the format:\n\n***Note:*** All values are big-endian unless noted.\n\n```\nstruct Index {\n    uint8     // Type Indicator (always 0x05)\n    char[3]   // Format Indicator (always \"SER\")\n    uint32    // Size Of Index (minus 32 bytes for this header section)\n    uint8[24] // Padding? (always seems to be filled with null bytes)\n    uint32    // Count Of Entries\n    Entry[N]  // List Of Entries (exactly matching count)\n}\n\nstruct Entry {\n    uint32    // ID Of Entry (seems to follow position in index, but not always)\n    uint32    // Little-Endian Type String Size\n    char[N]   // Type String (seems to be a type identifier)\n    uint32    // Little-Endian Source String Size\n    char[N]   // Source String (seems to be a source name, pre-build file/variable)\n    uint32    // Little-Endian Destination String Size\n    char[N]   // Destination String (seems to be the destination name, built asset)\n    uint64    // Resource File Byte Offset\n    uint32    // Actual Byte Size\n    uint32    // Packed Byte Size\n    uint16    // Flags\n    uint16    // Flags\n}\n```\n\nYou will see how the resource offset, actual, and packed byte sizes are used in\nthe section on `.resources` files.\n\nThe flags are interesting. If you shift the second set right by 2 bits it refers\nto which `.resources` file the data is stored in, so if you see `0` that is\n`gameN.resources`, `1` is `gameN_001.resources`, and on with `6` being\n`gameN_patch.resources`. You can verify this by seeing that the indexes will\nonly have flags set for their own patch level and previous patch levels.\n\nOne exception is if the top bit is set in the second set of flags. This seems to\nindicate that the data is stored in `shared_2_3.sharedrsc`. No idea why, maybe\nthis was done to avoid some kind of max open files limit for specific platforms.\nIn any case the data does seem to be in there and correct!\n\nNo idea what the first set of flags means, sometimes you see 32 in there!\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003e.resources And .sharedrsc Files\u003c/h3\u003e\u003c/summary\u003e\n\nEach `.resources` file can be at most `uint64 - 4` bytes long and `.sharedrsc`\nfiles are identical.\n\nThe format here is like the index but with basically no metadata other than a\n4 byte header, `04 53 45 52`. Always the `0x04` followed by the `\"SER\"` string\njust like in the index!\n\nThe rest is just raw data, we use the index to interpret it!\n\nEach entry in the index contains flags that tell you which `.resources` file to\nuse (within the same container). And within that resource file you simply grab\nthe packed number of bytes starting from the byte offset.\n\nIf the actual size recorded in the index entry is different (larger) than the\npacked size then we need to decompress the bytes we just read using zlib.\n\nOnce that's done you should have a chunk of data that exactly matches the actual\nsize and can be written out or viewed however you like.\n\nThere are a ton of files packed in that are plaintext (shader definitions, subtitles,\nparameters), but the vast majority of the data is binary files, I will document\ntheir formats as I interpret them.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003e.entities Files\u003c/h3\u003e\u003c/summary\u003e\n\nEach map in the game has a matching `.entities` file. These are plaintext files\nthat seem to be the core of each level.\n\nThey control:\n\n* World configuration. (environment, skybox, load params, ai params, etc.)\n* Player setup information.\n* All dynamic assets. (lights, clutter, chains, gates, visual and audio fx, phys objs, etc.)\n* Encounter/scenario logic. (kiscule diagram definitions that get run during gameplay)\n* HUD elements. (mission markers at least)\n\nI have written a simple parser for them in `entlib.py`.\n\n[See a more detailed description of the file format here.](docs/entities.md)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003e.mapinfo.decl Files\u003c/h3\u003e\u003c/summary\u003e\n\nEach map in the game has a matching `.mapinfo.decl` file. These are plaintext files\nthat seem to be the basic configuration for the level.\n\nThey control:\n\n* The map debug name.\n* The path to a matching `.map` file.\n    * Doesn't seem to affect anything if we change it...\n* How the loading process should work. (animations, layout, if it should wait at the end)\n* The players initial state. (in menu, etc.)\n\nSame format as the `.entities` files it seems, or close enough the same parser\nwill likely work.\n\nKnown values for m_initialState (tested in main menu level):\nARK_GAME_LOGIC_STATE_NONE\n    starts normally\nARK_GAME_LOGIC_STATE_PAUSE\n    starts you in the pause menu, which also pauses fog/fade in from black, etc.\nARK_GAME_LOGIC_STATE_INGAME\n    starts normally\nARK_GAME_LOGIC_STATE_READNOTE\n    shows a black screen\nARK_GAME_LOGIC_STATE_NOTIFICATION\n    shows black screen with uninitialized HUD and a tiny dot in the center\nARK_GAME_LOGIC_STATE_MAINMENU\n    shows the main menu\nARK_GAME_LOGIC_STATE_CINEMATIC\n    loads normally, player locked out of controls, but can look around, no HUD\nARK_GAME_LOGIC_STATE_POWERWHEEL\n    power wheel is shown but hides because you're not pressing TAB, leaves behind\n    a weird blur that falls off with distance abruptly, just to blur the hands\n    in regular gameplay i suspect\nARK_GAME_LOGIC_STATE_JOURNAL\n    loads into the journal menu, does leave behind the same blur artifact like\n    the POWERWHEEL state\nARK_GAME_LOGIC_STATE_BLACKMARKET\n    starts normally (need to test on a level with a black market)\nARK_GAME_LOGIC_STATE_CONVERSATION\n    shows a black screen\nARK_GAME_LOGIC_STATE_TUTORIAL\n    starts normally\nARK_GAME_LOGIC_STATE_RESULTS\n    starts in the end of level results screen, continuing takes you nowhere but\n    a textured blue/black background (need to test on a level with transitions)\nARK_GAME_LOGIC_STATE_CHARACTER_CHOICE\n    starts normally\nARK_GAME_LOGIC_STATE_GAMEOVER\n    starts in the game over screen, you can exit, restart, etc. normally.\nARK_GAME_LOGIC_STATE_DEMO\n    starts normally\nARK_GAME_LOGIC_STATE_MAP_TRANSITION\n    crashes as soon as the map finished loading\nARK_GAME_LOGIC_STATE_ANY\n    crashes as soon as the map finished loading\nARK_GAME_LOGIC_STATE_MAX\n    starts normally\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch3\u003ephysics.cpntplayerphysics.decl File\u003c/h3\u003e\u003c/summary\u003e\n\nThere is one of these in the whole game, it contains definitions for the players\nhitbox material and max slope as well as a list of every possible player \"shape\"\nwith the relevant hitbox size, step height, gravity strength, etc.\n\nThose \"shapes\" or \"postures\" include things like crouching, wall crouching,\npossessing hounds, fish, blood flys, grappling, etc.\n\nSame format as the `.entities` files it seems, or close enough the same parser\nwill likely work.\n\nA handy thing to do here for testing is adjusting the gravity strength for things\nlike crouching so you can float or fly up in a semi-freecam way to explore levels.\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchipolux%2Fdisrev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchipolux%2Fdisrev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchipolux%2Fdisrev/lists"}