mirror of https://github.com/pret/pokecrystal.git
125 lines
8.7 KiB
Markdown
125 lines
8.7 KiB
Markdown
# Nintendo 2DS/3DS Virtual Console Patch
|
|
|
|
The Nintendo Virtual Console is an emulator on the 2DS and 3DS consoles. It can emulate the Game Boy Color (among other consoles), while applying enhancements or modifications to some games, such as replacing Link Cable functionality with the DS' Wireless Link capabilities, or disabling Game Boy Printer features.
|
|
|
|
Game-specific enhancements are determined by a `.patch` file corresponding to the `.gbc` ROM file. These files are bundled together in a `.cia` file; creating such a file is outside the scope of this project.
|
|
|
|
|
|
## Build pokecrystal11.patch
|
|
|
|
To build **pokecrystal11.patch**:
|
|
|
|
```bash
|
|
make crystal11_vc
|
|
```
|
|
|
|
This will also create two ROM files, **pokecrystal11.gbc** and **pokecrystal11_vc.gbc**. The pokecrystal11_vc.gbc file has the patches already applied to it; do *not* use this file! The ROM file and patch file must share the same name, so use pokecrystal11.patch together with pokecrystal11.gbc.
|
|
|
|
|
|
## Custom files
|
|
|
|
There are a few files involved with building the `.patch` file, in addition to the ones used for building ROMs.
|
|
|
|
|
|
### vc/pokecrystal11.patch.template
|
|
|
|
The `.patch.template` file is the basis for the `.patch` file. Many numeric values in the `.patch` file are derived from the values of labels, constants, and ROM content; these values are abstracted into *commands* that get evaluated by `tools/make_patch` to output symbolic names as their actual values, formatted to match the original `.patch` file.
|
|
|
|
|
|
### vc/pokecrystal11.constants.asm
|
|
|
|
The `.constants.asm` file is used to create a `.constants.sym` file. Typical `.sym` files only list the values of *labels* (ROM banks and addresses); this file is used to list *constants* that are needed by the `.patch.template`. Any constants that the `.patch.template` refers to must be explicitly printed here with the `vc_const` macro.
|
|
|
|
|
|
### tools/make_patch.c
|
|
|
|
The program used to convert a `.patch.template` into a `.patch` file.
|
|
|
|
To convert `vc.patch.template` into `vc.patch`:
|
|
|
|
```bash
|
|
tools/make_patch labels.sym constants.sym patched.gbc original.gbc vc.patch.template vc.patch
|
|
```
|
|
|
|
For example, this is what `make crystal11_vc` does:
|
|
|
|
```bash
|
|
tools/make_patch pokecrystal11_vc.sym vc/pokecrystal11.constants.sym pokecrystal11_vc.gbc pokecrystal11.gbc vc/pokecrystal11.patch.template pokecrystal11.patch
|
|
```
|
|
|
|
|
|
## Patch types
|
|
|
|
**Hooks** do not directly modify the ROM; they just identify locations within the ROM code. When the emulated code execution reaches a hook, the emulator performs an emulation function. For example, the `Enable_GS_Ball_mobile_event` hook is located after the code to add a new Hall of Fame entry, and causes the emulator to edit the save file to enable the GS Ball event.
|
|
|
|
Hooks are defined with the `vc_hook` macro, which defines a label starting with "`.VC_`" for the patch template file to use.
|
|
|
|
**Patches** directly modify the contents of the ROM. This is done before emulation begins. For example, the `print_forbid_1` patch modifies an "`and A_BUTTON`" instruction to "`and 0`", so pressing A will not print Unown on the Game Boy Printer.
|
|
|
|
Patches are defined with the `vc_patch` and `vc_patch_end` macros; `vc_patch` defines a label starting with "`.VC_`", `vc_patch_end` defines a corresponding label with "`_End`" appended. Between these two macros, the code or data is conditionally different depending on whether or not a patch file is being built.
|
|
|
|
The sole purpose of creating `pokecrystal11_vc.gbc` and `pokecrystal11_vc.sym` is to make these labels and modifications available to `make_patch` for use in the patch template.
|
|
|
|
|
|
## Patch template syntax
|
|
|
|
**Comments** start at a semicolon "`;`" and continue until the end of the line. They are output as-is, without interpreting commands.
|
|
|
|
**Patch names** are contained in "`[`" brackets "`]`". They are output as-is, without interpreting commands.
|
|
|
|
Patch names also set the **current patch label**. This is the label starting with "`.VC_`" followed by the patch name, with any invalid characters (not letters "`A-Z`", digits "`0-9`", or underscore "`_`") converted to underscores "`_`". These labels are conditionally defined only when building the patch file with the `vc_hook` and `vc_patch` macros. For example, the patch name "`[fight begin]`" corresponds to the patch label "`.VC_fight_begin`", generated by the "`vc_hook fight_begin`" macro.
|
|
|
|
Patch names may designate an alternate for the label with an at-sign "`@`". This allows the label in the assembly source to have a more descriptive name, while still reproducing the original `.patch` file. For example, the patch name "`[BiographySave_ret@Enable_GS_Ball_mobile_event]`" corresponds to the label "`.VC_Enable_GS_Ball_mobile_event`" but is output as "`[BiographySave_ret]`".
|
|
|
|
**Commands** are contained in "`{`" braces "`}`". They are not output themselves, but may produce their own output when interpreted.
|
|
|
|
Commands are interpreted with a series of arguments, separated by whitespace (spaces, tabs, or newlines). Leading and trailing whitespace is ignored; for example, "`{ hex @ 4 }`" is interpreted the same as "`{hex @ 4}`".
|
|
|
|
Command names have variants to allow reproducing the exact formatting in a `.patch` file. If the command name is all lowercase, the output byte values use lowercase for hexadecimal digits A-F; if it is all uppercase, they use uppercase.
|
|
|
|
Some commands may output a **value series**, which is a series of two-digit hexadecimal bytes separated by spaces, preceded by a decimal count and a colon "`:`": "<code>a*N*: <i>v1</i> <i>v2</i> [...] <i>vN</i></code>". These commands have additional variants: if the command name ends in a slash "`/`", the count and colon are not output; or else, if it ends in an underscore "`_`", a space is output after the colon; otherwise, the count and colon are output without a space.
|
|
|
|
**Arguments** evaluate to numeric values. They may be any of the following:
|
|
|
|
- Literal numbers in decimal (base 10, e.g. "`42`"), hexadecimal (base 16, e.g. "`0x2a`"), or octal (base 8, e.g. "`052`"). They may start with a plus sign "`+`". Numbers should not be negative.
|
|
- Comparison operators: "`==`" is 0, "`>`" is 1, "`<`" is 2, "`>=`" is 3, "`<=`" is 4, "`!=`" is 5, and "`||`" is 0x11.
|
|
- Symbol names from the two `.sym` files provided to `make_patch` may evaluate as their relative address or their absolute offset, depending on the command. (Addresses are relative to the symbol's bank for ROM addresses, or to 0x8000, the start of all RAM, for RAM addresses.) They may also be followed by a plus sign and a literal number that gets added to the value.
|
|
- "`@`" evaluates as the address or absolute offset of the current patch/hook label, depending on the command.
|
|
|
|
Any other characters are output as-is.
|
|
|
|
|
|
## Patch template commands
|
|
|
|
|
|
### <code>{patch[ <i>offset</i>[ <i>length</i>]]}</code>
|
|
|
|
Outputs the bytes of the current patch as a value series, or as a hexadecimal number if there is only one byte. The bytes are found between the current patch label, and the label which is the current patch label plus "`_End`". An optional first argument is an *offset* to add to the current patch label before gathering the contents between it and the end label. An optional second argument is a *length* of bytes to output instead of the length between the start and end labels.
|
|
|
|
For example, if "`{patch}`" outputs "`a3:ab cd ef`", then "`{patch +1}`" outputs "`a2:cd ef`", and "`{patch 0 1}`" outputs "`0xab`".
|
|
|
|
Converting the patch template will print a warning if any differences exist between the original and patched ROMs, which are not covered by "`patch`" commands.
|
|
|
|
|
|
### <code>{dws <i>args</i>...}</code>
|
|
|
|
Outputs its arguments as a value series of little-endian 16-bit words. Symbol names or "`@`" are evaluated as their relative address.
|
|
|
|
For example, if "`{dws 42 0xabcd wCurSpecies}`" outputs "`a6:2a 00 cd ab 60 cf`", then "`{dws >= wCurSpecies+3}`" outputs "`a4:04 00 63 cf`".
|
|
|
|
|
|
### <code>{db <i>arg</i>}</code>
|
|
|
|
Outputs its argument as a single-byte value series. Symbol names or "`@`" are evaluated as their relative address.
|
|
|
|
For example, "`{db 0xEF}`" outputs "`a1:ef`".
|
|
|
|
|
|
### <code>{hex <i>arg</i>[ <i>padding</i>]}</code>
|
|
|
|
Outputs its first argument as a hexadecimal number. An optional second argument is the minimum length in digits; values shorter than it will be padded with leading zeros. Symbol names or "`@`" are evaluated as their absolute offset, or as their relative address if the command name ends in a tilde "`~`".
|
|
|
|
For example, if "`{hex @}`" outputs "`0x6789`", then "`{hex @+1 5}`" outputs "`0x0678a`".
|
|
|
|
This command has extra variants to reproduce inconsistent output casing: "`Hex`" prints the last three digits in lowercase and the rest uppercase; "`HEx`" prints the last two digits in lowercase and the rest uppercase; "`hEX`" prints the last three digits in uppercase and the rest lowercase; and "`heX`" prints the last two digits in uppercase and the rest lowercase.
|