Wiseguy
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
Publish Note

Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

Your note will be visible on your profile and discoverable by anyone.
Your note is now live.
This note is visible on your profile and discoverable online.
Everyone on the web can find and read all notes of this public team.
See published notes
Unpublish note
Please check the box to agree to the Community Guidelines.
View profile
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
1
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# N64 Recomp Modding ### Modding Discord Server If you're a mod developer and are interested in joining a community of other N64: Recompiled modders, join the Discord server at discord dot gg slash H2RAnQ4Vec. Please note that this server is not for user support or general discussion, issues should be reported on the project's repo. ### Mod file(s) Mods are distributed as a .nrm (N64 Recomp Mod). The .nrm file is generated by the RecompModTool utility in the N64: Recompiled repo. Because this is generated by the mod tool authors don't need to worry about the internals of the format, but details are listed below: An .nrm is just a renamed zip archive with the following contents: * A mod manifest file, which is a json file that describes the mod. It contains the target game id, mod id, mod version, mod author(s), and more. * This is the only mandatory file in a mod, though a mod with just a manifest wouldn't do anything. * (Optional) For mods with code: a mod symbol file and a mod binary. * The mod binary is simply a self-contained MIPS binary. This will be recompiled when the mod is loaded (explained more later). The binary will also be loaded into memory when the mod is active. * The mod symbol file describes the layout of sections and functions in the mod binary, as well as mod dependencies, exports, and imports (explained more later). It also describes relocations in the mod binary, which are used to shift the mod in RAM so that multiple mods can be loaded at once. * (Optional) Texture files for a texture pack. * Recomp will also accept .rtz texture packs. Recomp will recognize a recomp mod manifest in a .rtz texture pack, but will only allow fields that affect how the mod is displayed, meaning .rtz files can't include code. Recomp will populate a default manifest for .rtz texture packs if none is present. * (Optional) A patch file for the base ROM. * Two mods containing patches will be marked as incompatible. * Code that is modified by the patch file is not loaded. Code patches will need to be ported into a mod binary + mod symbol file. * Loading modified code from a patch file will be supported in the future. When that happens, modified code will not be detected automatically. Mod authors will need to create a list of modified functions in order for the modified versions to replace their original counterparts. * (Optional) A thumbnail image to show in the mod manager. * PNG and DDS image files are supported. The image must be named thumb.dds or thumb.png and placed in the root of the .nrm file. The easiest way to do this is to add it to the mod toml's `additional_files` list. ### Code mod types Mods with code can take two forms: * Normal mods, which get recompiled into native code using the "live recompiler" when the game is started. * This is the recommended form of code mod. Normal mods can be built on one platform and loaded on others without needing separate builds for each. * Offline recompiled mods, which generate C ahead of time and compile it into a dynamic library (DLL). This is separate from the ability for a mod to include dynamic libraries alongside the mod's code as mentioned previously. * This is not recommended, as it means the author will have to distribute platform-specific binaries. * Mainly intended for validating that live recompiler is working correctly for a mod. ### Writing code mods Mods can provide code in a few ways: * The primary way is to compile an elf file and run the recomp mod tool to generate a mod. * The most common approach for this will be to copy functions from the corresponding decompilation for a given recomp and edit them. * Mod authors can also copy asm functions from the game and edit them, which is useful for games without a complete decompilation. * Mod authors can also write their own mod binary and mod symbol file. * This is an incredibly niche option, but can be useful for supporting existing tools or porting existing mods. * Mods can also include additional dynamic libraries alongside the .nrm file. * The mod's manifest specifies dynamic libraries and the functions to export from them (more on exports later). * Mods authors will have to distribute a build of the dynamic library for each platform. The runtime will automatically pick the right one based on the platform's standard dynamic library format (.dll, .so, .dylib). ### Recomp mod tool The recomp mod tool is used build a mod file (.nrm). It takes a toml input for configuration. The latest release of the mod tool can be found in the Releases section of the N64Recomp repo: https://github.com/N64Recomp/N64Recomp/. An example toml can be found in the Majora's Mask Recompilation Mod Template: https://github.com/Zelda64Recomp/MMRecompModTemplate/blob/main/mod.toml If your mod includes a texture pack (i.e. includes an rt64.json), you can also create a config option to allow users to toggle the texture replacements. This is done by making a config option with the id set to `_recomp_texture_pack_enabled`. The name, description, and options names can be set to anything you want. The option must be of type `Enum` with 2 options. The first option will turn the textures off and the second will turn them on. An example of this config option can be found here: https://github.com/t0mtee/MMModernControllerOverhaul/blob/ba1b4964dc47c4212ae698c0505d7d9ee518db35/mod.toml#L92 ### Mod interactions The modding framework provides the following set of functionality to allow mods to interact with each other: * Mods can **hook** individual functions from the base game, allowing mod code to run directly before or after the hooked function. * Hooks allow for maximum compatibility between mods, so they should be used whenever possible over function replacement (see below). * Multiple mods can hook the same function. * Functions that are replaced by one mod can still be hooked by another mod. * Functions that have been replaced by the base recomp can also still be hooked by mods. * Entry hooks run before the target function. They can access the arguments that were passed to the target function by copying the target function's signature. * When using the standard recomp mod template, the `RECOMP_HOOK` macro can be added to a function to declare it as an entry hook for a target function in the original ROM. For example, if a mod was declaring an entry hook for a function named "Player_Init" it would look like this: ```c RECOMP_HOOK("Player_Init") void my_player_init_hook(Actor* thisx, PlayState* play) { /* function body here */ } ``` * The `thisx` and `play` arguments in this example will have the same values that were passed to Player_Init. * Return hooks run after the target function, regardless of what code path it followed. * Return hooks cannot access the arguments of the target function like an entry hook can, but you can use an entry hook in conjunction with a return hook to record the function arguments for use in the return hook. Be wary of recursive functions when using this approach. * When using the standard recomp mod template, the `RECOMP_HOOK_RETURN` macro can be added to a function to declare it as a return hook for a target function in the original ROM. For example, if a mod was declaring a return hook for a function named "Player_Init" it would look like this: ```c RECOMP_HOOK_RETURN("Player_Init") void my_player_init_return_hook() { /* function body here */ } ``` * Mods can replace individual functions from the base game. * If two mods replace the same function, they will be marked as incompatible. * If a mod replaces a function that was patched in the base recomp, the mod will fail to load. * Mods can use a forced replacement to replace a function that's patched in the base recomp, but this can be dangerous and is not recommended. * When using the standard recomp mod template, the `RECOMP_PATCH` macro can be added to a function with the same name as an original ROM function to make a patch. The names come from the symbol files used to run the recomp mod tool. For example, if a mod were replacing a function named "func_808333CC" it would look like this: ```c RECOMP_PATCH s32 func_808333CC(Player* this) { /* function body here */ } ``` * Mods can **export** functions for other mods to **import**. * For example, mod A can create a function called "foo" and export it, which would allow mod B to call it. * The `RECOMP_EXPORT` macro can be added to a function to export it. For example, if a mod named "testmod" was exporting a function called "testmod_do_stuff" it would look like this: ```c RECOMP_EXPORT u8 testmod_do_stuff(s32 param) { /* function body here */ } ``` * The `RECOMP_IMPORT` macro can be used to import a function from another mod. The first parameter is the name of the mod to import from, the second is the return type of the import, the third is the imported function's name, and the remaining ones are the imported function's arguments. For example, if another mod was importing the previous "testmod_do_stuff" function, it would look like this: ```c RECOMP_IMPORT("testmod", u8 testmod_do_stuff(s32 param)); ``` * The base recomp can also create exported functions that mods can import. To import those, use `*` as the mod name in the `RECOMP_IMPORT` macro. * Mods can import a symbol from themselves. This is useful when importing a native function from a dynamic library provided with the mod. To do so, use `.` as the mod name in the `RECOMP_IMPORT` macro. * Mods can create **events** that other mods can register **callbacks** for. * Events are called by the mod that creates them as if they were a function. * When an event is called, the runtime will run any callbacks registered to that event. * For example, mod A can create an event called "lorem" and then mod B can register a callback called "ipsum". * Mod A can then call the "lorem" event at any point in its code, which will in turn run mod B's "ipsum" callback. * The `RECOMP_DECLARE_EVENT` macro can be used to declare an event. The macro takes the event's function arguments as extra parameters. For example, if a mod named "testmod" declared an event named "testmod_event" that takes a "Player*" as an argument, it would look like this: ```c RECOMP_DECLARE_EVENT(testmod_event(Player* player)); ``` The mod can then call the event as if it were a function with the specified arguments. In this case, that would look like this: ```c testmod_event(player); ``` * The `RECOMP_CALLBACK` macro can be added to a function to register it as a callback for an event. The macro takes one argument, which is the name of the event to register the callback for. For example, if a mod was registering a function called "my_callback" to the previous "testmod_event" event, it would look like this: ```c RECOMP_CALLBACK("testmod", testmod_event) void my_callback(int val) { /* ... */ } ``` * Callbacks must have the same signature as the event. If they differ, undefined behavior will occur. * The base recomp can also create events that mods can register callbacks to. To register a callback for those, use `*` as the mod name in the `RECOMP_CALLBACK` macro. * This is useful in cases where mods want to add some code to a vanilla function but can't replace the function to avoid conflicts. * Mods can attach callbacks to their own events. To do so, use `.` as the mod name in the `RECOMP_CALLBACK` macro. ### Modding API The standard recomp runtime will provide a common set of functionality to mods in the form of a modding API, which will be present in all recomps. This includes memory allocation functions, reading config options, some basic data structures, and a UI framework. The functions provided by this API can be found in the header files of the mod template, e.g. `recomputils.h`, `recompconfig.h`, `recompdata.h`, and `recompui.h.` Individual recomps will also be able to add their own functionality to the modding API. This will come in the form of **exports** and **events** provided by the base recomp. These can come from the base recomp's patches or from the recomp's native code. For example, Zelda 64: Recompiled provides additional APIs found in the mod template's `z64recomp_api.h` header file.

Import from clipboard

Paste your markdown or webpage here...

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template has been removed or transferred.
Upgrade
All
  • All
  • Team
No template.

Create a template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

Slide Example

API Docs

Edit in VSCode

Install browser extension

Contacts

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Get Full History Access

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

Note content is identical to the latest version.
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully