Build the Virtual Console patch with make crystal11_vc (#882)

Fixes #813
This commit is contained in:
vulcandth
2022-03-12 17:34:04 -06:00
committed by GitHub
parent 775b5d046c
commit 31c3c94d64
28 changed files with 1538 additions and 8 deletions

3
.gitattributes vendored
View File

@ -28,6 +28,9 @@
*.attrmap binary diff=hex *.attrmap binary diff=hex
*.tilemap binary diff=hex *.tilemap binary diff=hex
# Declare files that will always have CRLF line endings on checkout.
*.patch.template text eol=crlf linguist-language=INI
# these are generated but just in case # these are generated but just in case
*.lz binary diff=hex *.lz binary diff=hex
*.2bpp binary diff=hex *.2bpp binary diff=hex

1
.gitignore vendored
View File

@ -17,6 +17,7 @@ gfx/pokemon/*/frames.asm
# compiled roms # compiled roms
*.gbc *.gbc
*.gb *.gb
*.patch
# rgbds extras # rgbds extras
*.map *.map

View File

@ -1,4 +1,9 @@
roms := pokecrystal.gbc pokecrystal11.gbc pokecrystal_au.gbc pokecrystal_debug.gbc pokecrystal11_debug.gbc roms := pokecrystal.gbc \
pokecrystal11.gbc \
pokecrystal_au.gbc \
pokecrystal_debug.gbc \
pokecrystal11_debug.gbc
patches := pokecrystal11.patch
rom_obj := \ rom_obj := \
audio.o \ audio.o \
@ -23,6 +28,7 @@ pokecrystal11_obj := $(rom_obj:.o=11.o)
pokecrystal_au_obj := $(rom_obj:.o=_au.o) pokecrystal_au_obj := $(rom_obj:.o=_au.o)
pokecrystal_debug_obj := $(rom_obj:.o=_debug.o) pokecrystal_debug_obj := $(rom_obj:.o=_debug.o)
pokecrystal11_debug_obj := $(rom_obj:.o=11_debug.o) pokecrystal11_debug_obj := $(rom_obj:.o=11_debug.o)
pokecrystal11_vc_obj := $(rom_obj:.o=11_vc.o)
### Build tools ### Build tools
@ -54,16 +60,42 @@ crystal11: pokecrystal11.gbc
crystal_au: pokecrystal_au.gbc crystal_au: pokecrystal_au.gbc
crystal_debug: pokecrystal_debug.gbc crystal_debug: pokecrystal_debug.gbc
crystal11_debug: pokecrystal11_debug.gbc crystal11_debug: pokecrystal11_debug.gbc
crystal11_vc: pokecrystal11.patch
clean: tidy clean: tidy
find gfx \( -name "*.[12]bpp" -o -name "*.lz" -o -name "*.gbcpal" -o -name "*.sgb.tilemap" \) -delete find gfx \
find gfx/pokemon -mindepth 1 ! -path "gfx/pokemon/unown/*" \( -name "bitmask.asm" -o -name "frames.asm" -o -name "front.animated.tilemap" -o -name "front.dimensions" \) -delete \( -name "*.[12]bpp" \
-o -name "*.lz" \
-o -name "*.gbcpal" \
-o -name "*.sgb.tilemap" \) \
-delete
find gfx/pokemon -mindepth 1 \
! -path "gfx/pokemon/unown/*" \
\( -name "bitmask.asm" \
-o -name "frames.asm" \
-o -name "front.animated.tilemap" \
-o -name "front.dimensions" \) \
-delete
tidy: tidy:
$(RM) $(roms) $(pokecrystal_obj) $(pokecrystal11_obj) $(pokecrystal_au_obj) $(pokecrystal_debug_obj) $(pokecrystal11_debug_obj) $(roms:.gbc=.map) $(roms:.gbc=.sym) rgbdscheck.o $(RM) $(roms) \
$(roms:.gbc=.sym) \
$(roms:.gbc=.map) \
$(patches) \
$(patches:.patch=_vc.gbc) \
$(patches:.patch=_vc.sym) \
$(patches:.patch=_vc.map) \
$(patches:%.patch=vc/%.constants.sym) \
$(pokecrystal_obj) \
$(pokecrystal11_obj) \
$(pokecrystal11_vc_obj) \
$(pokecrystal_au_obj) \
$(pokecrystal_debug_obj) \
$(pokecrystal11_debug_obj) \
rgbdscheck.o
$(MAKE) clean -C tools/ $(MAKE) clean -C tools/
compare: $(roms) compare: $(roms) $(patches)
@$(SHA1) -c roms.sha1 @$(SHA1) -c roms.sha1
tools: tools:
@ -81,6 +113,12 @@ $(pokecrystal11_obj): RGBASMFLAGS += -D _CRYSTAL11
$(pokecrystal_au_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL_AU $(pokecrystal_au_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL_AU
$(pokecrystal_debug_obj): RGBASMFLAGS += -D _DEBUG $(pokecrystal_debug_obj): RGBASMFLAGS += -D _DEBUG
$(pokecrystal11_debug_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _DEBUG $(pokecrystal11_debug_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _DEBUG
$(pokecrystal11_vc_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL11_VC
%.patch: %_vc.sym vc/%.constants.sym %_vc.gbc %.gbc vc/%.patch.template
tools/make_patch $^ $@
%.sym: ;
rgbdscheck.o: rgbdscheck.asm rgbdscheck.o: rgbdscheck.asm
$(RGBASM) -o $@ $< $(RGBASM) -o $@ $<
@ -105,6 +143,11 @@ $(foreach obj, $(pokecrystal11_obj), $(eval $(call DEP,$(obj),$(obj:11.o=.asm)))
$(foreach obj, $(pokecrystal_au_obj), $(eval $(call DEP,$(obj),$(obj:_au.o=.asm)))) $(foreach obj, $(pokecrystal_au_obj), $(eval $(call DEP,$(obj),$(obj:_au.o=.asm))))
$(foreach obj, $(pokecrystal_debug_obj), $(eval $(call DEP,$(obj),$(obj:_debug.o=.asm)))) $(foreach obj, $(pokecrystal_debug_obj), $(eval $(call DEP,$(obj),$(obj:_debug.o=.asm))))
$(foreach obj, $(pokecrystal11_debug_obj), $(eval $(call DEP,$(obj),$(obj:11_debug.o=.asm)))) $(foreach obj, $(pokecrystal11_debug_obj), $(eval $(call DEP,$(obj),$(obj:11_debug.o=.asm))))
$(foreach obj, $(pokecrystal11_vc_obj), $(eval $(call DEP,$(obj),$(obj:11_vc.o=.asm))))
# Dependencies for VC files that need to run scan_includes
%.constants.sym: %.constants.asm $(shell tools/scan_includes %.constants.asm) | rgbdscheck.o
$(RGBASM) $< > $@
endif endif
@ -114,10 +157,12 @@ pokecrystal11_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10
pokecrystal_au_opt = -Cjv -t PM_CRYSTAL -i BYTU -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0 pokecrystal_au_opt = -Cjv -t PM_CRYSTAL -i BYTU -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
pokecrystal_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0 pokecrystal_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 0 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
pokecrystal11_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0 pokecrystal11_debug_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
pokecrystal11_vc_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
pokecrystal_base = us pokecrystal_base = us
pokecrystal11_base = us pokecrystal11_base = us
pokecrystal_au_base = us pokecrystal_au_base = us
pokecrystal11_vc_base = us
pokecrystal_debug_base = dbg pokecrystal_debug_base = dbg
pokecrystal11_debug_base = dbg pokecrystal11_debug_base = dbg

View File

@ -9,6 +9,7 @@ It builds the following ROMs:
- Pokemon - Crystal Version (A) [C][!].gbc `sha1: a0fc810f1d4e124434f7be2c989ab5b5892ddf36` - Pokemon - Crystal Version (A) [C][!].gbc `sha1: a0fc810f1d4e124434f7be2c989ab5b5892ddf36`
- CRYSTAL_ps3_010328d.bin `sha1: c60d57a24bbe8ecf7cba54ab3f90669f97bd330d` - CRYSTAL_ps3_010328d.bin `sha1: c60d57a24bbe8ecf7cba54ab3f90669f97bd330d`
- CRYSTAL_ps3_us_revise_010710d.bin `sha1: 391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4` - CRYSTAL_ps3_us_revise_010710d.bin `sha1: 391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4`
- CGBBYTE1.784.patch `sha1: a25517f60ca0e887d39ec698aa56a0040532a4b3`
To set up the repository, see [INSTALL.md](INSTALL.md). To set up the repository, see [INSTALL.md](INSTALL.md).

View File

@ -21,6 +21,7 @@ These pages are for documenting pieces of the [pokecrystal](https://github.com/p
- [battle_anim_commands.md](battle_anim_commands.md) - [battle_anim_commands.md](battle_anim_commands.md)
- [move_effect_commands.md](move_effect_commands.md) - [move_effect_commands.md](move_effect_commands.md)
- [music_commands.md](music_commands.md) - [music_commands.md](music_commands.md)
- [vc_patch.md](vc_patch.md)
## Other subsystems ## Other subsystems

124
docs/vc_patch.md Normal file
View File

@ -0,0 +1,124 @@
# 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 `BiographySave_ret` 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`", underscore "`_`", at sign "`@`", or hash "`#`") 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.
**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}`".
Some commands may output a **value series**, which is a series of two-digit hexadecimal bytes separated by spaces, preceded by a decimal count: "<code>a*N*: <i>v1</i> <i>v2</i> [...] <i>vN</i></code>".
Some 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. For commands which output a value series, if the command name ends in an underscore, a space is output after the colon preceding the values; if not, then it is not.
**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 may 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 bank-relative address, or their absolute offset in the ROM, depending on the command. 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.
Any other characters are output as-is.
## Patch template commands
### <code>{patch[ <i>offset</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 argument is an *offset* to add to the current patch label before gathering the contents between it and the end label.
For example, if "`{patch}`" outputs "`a3:ab cd ef`", then "`{patch +1}`" outputs "`a2:cd ef`", and "`{patch +2}`" outputs "`0xef`".
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.
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.
For example, "`{hex 0xabcd 5}`" outputs "`0x0abcd`".

View File

@ -21,6 +21,7 @@ DoBattleTransition:
ld hl, hVBlank ld hl, hVBlank
ld a, [hl] ld a, [hl]
push af push af
vc_hook FPA_link_fight_begin
ld [hl], $1 ld [hl], $1
.loop .loop
@ -58,6 +59,7 @@ DoBattleTransition:
ld a, $1 ; unnecessary bankswitch? ld a, $1 ; unnecessary bankswitch?
ldh [rSVBK], a ldh [rSVBK], a
pop af pop af
vc_hook FPA_link_fight_End4
ldh [hVBlank], a ldh [hVBlank], a
call DelayFrame call DelayFrame
ret ret
@ -310,6 +312,7 @@ StartTrainerBattle_Flash:
dc 0, 0, 0, 1 dc 0, 0, 0, 1
StartTrainerBattle_SetUpForWavyOutro: StartTrainerBattle_SetUpForWavyOutro:
vc_hook FPA_link_fight_End0
farcall RespawnPlayerAndOpponent farcall RespawnPlayerAndOpponent
ld a, BANK(wLYOverrides) ld a, BANK(wLYOverrides)
ldh [rSVBK], a ldh [rSVBK], a
@ -367,6 +370,7 @@ StartTrainerBattle_SineWave:
ret ret
StartTrainerBattle_SetUpForSpinOutro: StartTrainerBattle_SetUpForSpinOutro:
vc_hook FPA_link_fight_End1
farcall RespawnPlayerAndOpponent farcall RespawnPlayerAndOpponent
ld a, BANK(wLYOverrides) ld a, BANK(wLYOverrides)
ldh [rSVBK], a ldh [rSVBK], a
@ -509,6 +513,7 @@ ENDM
.wedge5: db 4, 0, 3, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, 1, -1 .wedge5: db 4, 0, 3, 0, 3, 0, 2, 0, 2, 0, 1, 0, 1, 0, 1, -1
StartTrainerBattle_SetUpForRandomScatterOutro: StartTrainerBattle_SetUpForRandomScatterOutro:
vc_hook FPA_link_fight_End2
farcall RespawnPlayerAndOpponent farcall RespawnPlayerAndOpponent
ld a, BANK(wLYOverrides) ld a, BANK(wLYOverrides)
ldh [rSVBK], a ldh [rSVBK], a
@ -763,6 +768,7 @@ StartTrainerBattle_DrawSineWave:
calc_sine_wave calc_sine_wave
StartTrainerBattle_ZoomToBlack: StartTrainerBattle_ZoomToBlack:
vc_hook FPA_link_fight_End3
farcall RespawnPlayerAndOpponent farcall RespawnPlayerAndOpponent
ld de, .boxes ld de, .boxes

View File

@ -8940,6 +8940,7 @@ InitBattleDisplay:
predef PlaceGraphic predef PlaceGraphic
xor a xor a
ldh [hWY], a ldh [hWY], a
vc_hook fight_begin
ldh [rWY], a ldh [rWY], a
call WaitBGMap call WaitBGMap
call HideSprites call HideSprites

View File

@ -58,12 +58,20 @@ BattleAnimRunScript:
farcall CheckBattleScene farcall CheckBattleScene
jr c, .disabled jr c, .disabled
vc_hook FPA_001_Begin
vc_hook FPA_002_Begin
vc_hook FPA_003_Begin
vc_hook FPA_004_Begin
vc_hook FPA_005_Begin
vc_hook FPA_006_Begin
vc_hook FPA_007_Begin
call BattleAnimClearHud call BattleAnimClearHud
call RunBattleAnimScript call RunBattleAnimScript
call BattleAnimAssignPals call BattleAnimAssignPals
call BattleAnimRequestPals call BattleAnimRequestPals
vc_hook FPA_001_End
xor a xor a
ldh [hSCX], a ldh [hSCX], a
ldh [hSCY], a ldh [hSCY], a
@ -673,6 +681,7 @@ BattleAnimCmd_5GFX:
.loop .loop
ld a, [wBattleAnimGFXTempTileID] ld a, [wBattleAnimGFXTempTileID]
cp (vTiles1 - vTiles0) / LEN_2BPP_TILE - BATTLEANIM_BASE_TILE cp (vTiles1 - vTiles0) / LEN_2BPP_TILE - BATTLEANIM_BASE_TILE
vc_hook FPA_042801_Begin
ret nc ret nc
call GetBattleAnimByte call GetBattleAnimByte
ld [hli], a ld [hli], a

View File

@ -74,7 +74,13 @@ _UnownPrinter:
jr nz, .pressed_b jr nz, .pressed_b
ldh a, [hJoyPressed] ldh a, [hJoyPressed]
vc_patch print_forbid_1
if DEF(_CRYSTAL11_VC)
and 0
else
and A_BUTTON and A_BUTTON
endc
vc_patch_end
jr nz, .pressed_a jr nz, .pressed_a
call .LeftRight call .LeftRight

View File

@ -1033,6 +1033,7 @@ endr
.FinalPush: .FinalPush:
ld hl, MltReq1Packet ld hl, MltReq1Packet
call _PushSGBPals call _PushSGBPals
vc_hook Network_RESET
jp SGBDelayCycles jp SGBDelayCycles
SGBBorder_PushBGPals: SGBBorder_PushBGPals:

View File

@ -67,7 +67,13 @@ Gen2ToGen1LinkComms:
.player_1 .player_1
ld de, MUSIC_NONE ld de, MUSIC_NONE
call PlayMusic call PlayMusic
vc_patch NetworkDelay1
if DEF(_CRYSTAL11_VC)
ld c, 26
else
ld c, 3 ld c, 3
endc
vc_patch_end
call DelayFrames call DelayFrames
xor a xor a
ldh [rIF], a ldh [rIF], a
@ -77,6 +83,7 @@ Gen2ToGen1LinkComms:
ld hl, wLinkBattleRNPreamble ld hl, wLinkBattleRNPreamble
ld de, wEnemyMon ld de, wEnemyMon
ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
vc_hook Network358
call Serial_ExchangeBytes call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE ld a, SERIAL_NO_DATA_BYTE
ld [de], a ld [de], a
@ -84,6 +91,7 @@ Gen2ToGen1LinkComms:
ld hl, wLinkData ld hl, wLinkData
ld de, wOTPartyData ld de, wOTPartyData
ld bc, SERIAL_PREAMBLE_LENGTH + NAME_LENGTH + 1 + PARTY_LENGTH + 1 + (REDMON_STRUCT_LENGTH + NAME_LENGTH * 2) * PARTY_LENGTH + 3 ld bc, SERIAL_PREAMBLE_LENGTH + NAME_LENGTH + 1 + PARTY_LENGTH + 1 + (REDMON_STRUCT_LENGTH + NAME_LENGTH * 2) * PARTY_LENGTH + 3
vc_hook Network359
call Serial_ExchangeBytes call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE ld a, SERIAL_NO_DATA_BYTE
ld [de], a ld [de], a
@ -91,6 +99,7 @@ Gen2ToGen1LinkComms:
ld hl, wPlayerPatchLists ld hl, wPlayerPatchLists
ld de, wOTPatchLists ld de, wOTPatchLists
ld bc, 200 ld bc, 200
vc_hook Network364
call Serial_ExchangeBytes call Serial_ExchangeBytes
xor a xor a
@ -224,7 +233,13 @@ Gen2ToGen2LinkComms:
.player_1 .player_1
ld de, MUSIC_NONE ld de, MUSIC_NONE
call PlayMusic call PlayMusic
vc_patch NetworkDelay4
if DEF(_CRYSTAL11_VC)
ld c, 26
else
ld c, 3 ld c, 3
endc
vc_patch_end
call DelayFrames call DelayFrames
xor a xor a
ldh [rIF], a ldh [rIF], a
@ -234,6 +249,7 @@ Gen2ToGen2LinkComms:
ld hl, wLinkBattleRNPreamble ld hl, wLinkBattleRNPreamble
ld de, wEnemyMon ld de, wEnemyMon
ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
vc_hook Network360
call Serial_ExchangeBytes call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE ld a, SERIAL_NO_DATA_BYTE
ld [de], a ld [de], a
@ -241,6 +257,7 @@ Gen2ToGen2LinkComms:
ld hl, wLinkData ld hl, wLinkData
ld de, wOTPartyData ld de, wOTPartyData
ld bc, SERIAL_PREAMBLE_LENGTH + NAME_LENGTH + 1 + PARTY_LENGTH + 1 + 2 + (PARTYMON_STRUCT_LENGTH + NAME_LENGTH * 2) * PARTY_LENGTH + 3 ld bc, SERIAL_PREAMBLE_LENGTH + NAME_LENGTH + 1 + PARTY_LENGTH + 1 + 2 + (PARTYMON_STRUCT_LENGTH + NAME_LENGTH * 2) * PARTY_LENGTH + 3
vc_hook Network361
call Serial_ExchangeBytes call Serial_ExchangeBytes
ld a, SERIAL_NO_DATA_BYTE ld a, SERIAL_NO_DATA_BYTE
ld [de], a ld [de], a
@ -248,6 +265,7 @@ Gen2ToGen2LinkComms:
ld hl, wPlayerPatchLists ld hl, wPlayerPatchLists
ld de, wOTPatchLists ld de, wOTPatchLists
ld bc, 200 ld bc, 200
vc_hook Network362
call Serial_ExchangeBytes call Serial_ExchangeBytes
ld a, [wLinkMode] ld a, [wLinkMode]
@ -256,6 +274,7 @@ Gen2ToGen2LinkComms:
ld hl, wLinkPlayerMail ld hl, wLinkPlayerMail
ld de, wLinkOTMail ld de, wLinkOTMail
ld bc, wLinkPlayerMailEnd - wLinkPlayerMail ld bc, wLinkPlayerMailEnd - wLinkPlayerMail
vc_hook Network363
call ExchangeBytes call ExchangeBytes
.not_trading .not_trading
@ -1608,6 +1627,7 @@ ExitLinkCommunications:
ldh [rSC], a ldh [rSC], a
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a ldh [rSC], a
vc_hook ret_heya
ret ret
GSPlaceTradeScreenFooter: ; unreferenced GSPlaceTradeScreenFooter: ; unreferenced
@ -2009,6 +2029,7 @@ LinkTrade:
ld de, String_TradeCompleted ld de, String_TradeCompleted
call PlaceString call PlaceString
farcall Link_WaitBGMap farcall Link_WaitBGMap
vc_hook save_game_end
ld c, 50 ld c, 50
call DelayFrames call DelayFrames
ld a, [wLinkMode] ld a, [wLinkMode]
@ -2161,7 +2182,13 @@ GetIncompatibleMonName:
ret ret
EnterTimeCapsule: EnterTimeCapsule:
vc_patch NetworkDelay2
if DEF(_CRYSTAL11_VC)
ld c, 26
else
ld c, 10 ld c, 10
endc
vc_patch_end
call DelayFrames call DelayFrames
ld a, $4 ld a, $4
call Link_EnsureSync call Link_EnsureSync
@ -2218,6 +2245,7 @@ WaitForOtherPlayerToExit:
ld [hl], a ld [hl], a
ldh [hVBlank], a ldh [hVBlank], a
ld [wLinkMode], a ld [wLinkMode], a
vc_hook term_exit
ret ret
SetBitsForLinkTradeRequest: SetBitsForLinkTradeRequest:
@ -2282,6 +2310,7 @@ WaitForLinkedFriend:
ld a, (0 << rSC_ON) | (0 << rSC_CLOCK) ld a, (0 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a ldh [rSC], a
ld a, (1 << rSC_ON) | (0 << rSC_CLOCK) ld a, (1 << rSC_ON) | (0 << rSC_CLOCK)
vc_hook linkCable_fake_begin
ldh [rSC], a ldh [rSC], a
ld a, [wLinkTimeoutFrames] ld a, [wLinkTimeoutFrames]
dec a dec a
@ -2374,7 +2403,13 @@ CheckLinkTimeout_Gen2:
ld a, $6 ld a, $6
ld [wPlayerLinkAction], a ld [wPlayerLinkAction], a
ld hl, wLinkTimeoutFrames ld hl, wLinkTimeoutFrames
vc_patch NetworkDelay6
if DEF(_CRYSTAL11_VC)
ld a, $3
else
ld a, 1 ld a, 1
endc
vc_patch_end
ld [hli], a ld [hli], a
ld [hl], 50 ld [hl], 50
call Link_CheckCommunicationError call Link_CheckCommunicationError
@ -2395,6 +2430,7 @@ CheckLinkTimeout_Gen2:
Link_CheckCommunicationError: Link_CheckCommunicationError:
xor a xor a
ldh [hSerialReceivedNewData], a ldh [hSerialReceivedNewData], a
vc_hook linkCable_fake_end
ld a, [wLinkTimeoutFrames] ld a, [wLinkTimeoutFrames]
ld h, a ld h, a
ld a, [wLinkTimeoutFrames + 1] ld a, [wLinkTimeoutFrames + 1]
@ -2425,6 +2461,7 @@ Link_CheckCommunicationError:
.CheckConnected: .CheckConnected:
call WaitLinkTransfer call WaitLinkTransfer
ld hl, wLinkTimeoutFrames ld hl, wLinkTimeoutFrames
vc_hook Network_RECHECK
ld a, [hli] ld a, [hli]
inc a inc a
ret nz ret nz
@ -2433,7 +2470,13 @@ Link_CheckCommunicationError:
ret ret
.AcknowledgeSerial: .AcknowledgeSerial:
vc_patch NetworkDelay3
if DEF(_CRYSTAL11_VC)
ld b, 26
else
ld b, 10 ld b, 10
endc
vc_patch_end
.loop .loop
call DelayFrame call DelayFrame
call LinkDataReceived call LinkDataReceived
@ -2460,8 +2503,10 @@ TryQuickSave:
ld a, [wChosenCableClubRoom] ld a, [wChosenCableClubRoom]
push af push af
farcall Link_SaveGame farcall Link_SaveGame
vc_hook linkCable_block_input
ld a, TRUE ld a, TRUE
jr nc, .return_result jr nc, .return_result
vc_hook linkCable_block_input2
xor a ; FALSE xor a ; FALSE
.return_result .return_result
ld [wScriptVar], a ld [wScriptVar], a
@ -2498,6 +2543,7 @@ CheckBothSelectedSameRoom:
ret ret
TimeCapsule: TimeCapsule:
vc_hook to_play2_mons1
ld a, LINK_TIMECAPSULE ld a, LINK_TIMECAPSULE
ld [wLinkMode], a ld [wLinkMode], a
call DisableSpriteUpdates call DisableSpriteUpdates
@ -2508,6 +2554,7 @@ TimeCapsule:
ret ret
TradeCenter: TradeCenter:
vc_hook to_play2_trade
ld a, LINK_TRADECENTER ld a, LINK_TRADECENTER
ld [wLinkMode], a ld [wLinkMode], a
call DisableSpriteUpdates call DisableSpriteUpdates
@ -2518,6 +2565,7 @@ TradeCenter:
ret ret
Colosseum: Colosseum:
vc_hook to_play2_battle
ld a, LINK_COLOSSEUM ld a, LINK_COLOSSEUM
ld [wLinkMode], a ld [wLinkMode], a
call DisableSpriteUpdates call DisableSpriteUpdates
@ -2532,6 +2580,7 @@ CloseLink:
ld [wLinkMode], a ld [wLinkMode], a
ld c, 3 ld c, 3
call DelayFrames call DelayFrames
vc_hook room_check
jp Link_ResetSerialRegistersAfterLinkClosure jp Link_ResetSerialRegistersAfterLinkClosure
FailedLinkToPast: FailedLinkToPast:

View File

@ -37,14 +37,23 @@ DoMysteryGift:
; Prepare the first of two messages for wMysteryGiftPartnerData ; Prepare the first of two messages for wMysteryGiftPartnerData
farcall StageDataForMysteryGift farcall StageDataForMysteryGift
call ClearMysteryGiftTrainer call ClearMysteryGiftTrainer
vc_patch infrared_fake_0
if DEF(_CRYSTAL11_VC)
farcall StagePartyDataForMysteryGift
call ClearMysteryGiftTrainer
nop
else
ld a, 2 ld a, 2
ld [wMysteryGiftMessageCount], a ld [wMysteryGiftMessageCount], a
ld a, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData ld a, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
ld [wMysteryGiftStagedDataLength], a ld [wMysteryGiftStagedDataLength], a
endc
vc_patch_end
ldh a, [rIE] ldh a, [rIE]
push af push af
call ExchangeMysteryGiftData call ExchangeMysteryGiftData
vc_hook infrared_fake_4
ld d, a ld d, a
xor a xor a
ldh [rIF], a ldh [rIF], a
@ -260,6 +269,26 @@ DoMysteryGift:
jp CloseSRAM jp CloseSRAM
ExchangeMysteryGiftData: ExchangeMysteryGiftData:
vc_hook infrared_fake_2
vc_patch infrared_fake_1
if DEF(_CRYSTAL11_VC)
ld d, $ef
.loop
dec d
ld a, d
or a
jr nz, .loop
vc_hook infrared_fake_3
nop
cp MG_CANCELED
.restart ; same location as unpatched .restart
ret z
nop
nop
cp MG_OKAY
jr nz, ExchangeMysteryGiftData
ret
else
di di
farcall ClearChannels farcall ClearChannels
call InitializeIRCommunicationInterrupts call InitializeIRCommunicationInterrupts
@ -268,6 +297,8 @@ ExchangeMysteryGiftData:
call BeginIRCommunication call BeginIRCommunication
call InitializeIRCommunicationRoles call InitializeIRCommunicationRoles
ldh a, [hMGStatusFlags] ldh a, [hMGStatusFlags]
endc
vc_patch_end
cp MG_CANCELED cp MG_CANCELED
jp z, EndOrContinueMysteryGiftIRCommunication jp z, EndOrContinueMysteryGiftIRCommunication
cp MG_OKAY cp MG_OKAY

View File

@ -362,7 +362,9 @@ Menu_WasButtonPressed:
call GetMenuJoypad call GetMenuJoypad
and a and a
ret z ret z
vc_hook print_forbid_3
scf scf
vc_hook print_forbid_2
ret ret
_2DMenuInterpretJoypad: _2DMenuInterpretJoypad:

View File

@ -161,6 +161,15 @@ AddHallOfFameEntry:
ld bc, wHallOfFamePokemonListEnd - wHallOfFamePokemonList + 1 ld bc, wHallOfFamePokemonListEnd - wHallOfFamePokemonList + 1
call CopyBytes call CopyBytes
call CloseSRAM call CloseSRAM
; This vc_hook causes the Virtual Console to set [sMobileEventIndex] and [sMobileEventIndexBackup]
; to MOBILE_EVENT_OBJECT_GS_BALL ($b), which enables you to get the GS Ball, take it to Kurt, and
; encounter Celebi. It assumes that sMobileEventIndex and sMobileEventIndexBackup are at their
; original addresses.
vc_hook BiographySave_ret
vc_assert BANK(sMobileEventIndex) == $1 && sMobileEventIndex == $be3c, \
"sMobileEventIndex is no longer located at 01:be3c."
vc_assert BANK(sMobileEventIndexBackup) == $1 && sMobileEventIndexBackup == $be44, \
"sMobileEventIndexBackup is no longer located at 01:be44."
ret ret
SaveGameData: SaveGameData:

View File

@ -389,6 +389,7 @@ Script_yesorno:
ld a, TRUE ld a, TRUE
.no .no
ld [wScriptVar], a ld [wScriptVar], a
vc_hook E_YESNO
ret ret
Script_loadmenu: Script_loadmenu:

View File

@ -356,6 +356,7 @@ Pokedex_UpdateDexEntryScreen:
ld a, [hl] ld a, [hl]
and B_BUTTON and B_BUTTON
jr nz, .return_to_prev_screen jr nz, .return_to_prev_screen
vc_hook print_forbid_5
ld a, [hl] ld a, [hl]
and A_BUTTON and A_BUTTON
jr nz, .do_menu_action jr nz, .do_menu_action

View File

@ -67,7 +67,13 @@ ReadAnyMail:
ldh a, [hJoyPressed] ldh a, [hJoyPressed]
and A_BUTTON | B_BUTTON | START and A_BUTTON | B_BUTTON | START
jr z, .loop jr z, .loop
vc_patch print_forbid_4
if DEF(_CRYSTAL11_VC)
and 0
else
and START and START
endc
vc_patch_end
jr nz, .pressed_start jr nz, .pressed_start
ret ret

View File

@ -290,6 +290,7 @@ Serial_SyncAndExchangeNybble:: ; unreferenced
jp WaitLinkTransfer ; pointless jp WaitLinkTransfer ; pointless
WaitLinkTransfer:: WaitLinkTransfer::
vc_hook send_send_buf2
ld a, $ff ld a, $ff
ld [wOtherPlayerLinkAction], a ld [wOtherPlayerLinkAction], a
.loop .loop
@ -317,14 +318,26 @@ WaitLinkTransfer::
inc a inc a
jr z, .loop jr z, .loop
vc_patch Network10
if DEF(_CRYSTAL11_VC)
ld b, 26
else
ld b, 10 ld b, 10
endc
vc_patch_end
.receive .receive
call DelayFrame call DelayFrame
call LinkTransfer call LinkTransfer
dec b dec b
jr nz, .receive jr nz, .receive
vc_patch Network11
if DEF(_CRYSTAL11_VC)
ld b, 26
else
ld b, 10 ld b, 10
endc
vc_patch_end
.acknowledge .acknowledge
call DelayFrame call DelayFrame
call LinkDataReceived call LinkDataReceived
@ -333,6 +346,7 @@ WaitLinkTransfer::
ld a, [wOtherPlayerLinkAction] ld a, [wOtherPlayerLinkAction]
ld [wOtherPlayerLinkMode], a ld [wOtherPlayerLinkMode], a
vc_hook send_send_buf2_ret
ret ret
LinkTransfer:: LinkTransfer::

View File

@ -6,6 +6,7 @@ INCLUDE "macros/data.asm"
INCLUDE "macros/code.asm" INCLUDE "macros/code.asm"
INCLUDE "macros/gfx.asm" INCLUDE "macros/gfx.asm"
INCLUDE "macros/coords.asm" INCLUDE "macros/coords.asm"
INCLUDE "macros/vc.asm"
INCLUDE "macros/scripts/audio.asm" INCLUDE "macros/scripts/audio.asm"
INCLUDE "macros/scripts/maps.asm" INCLUDE "macros/scripts/maps.asm"

Some files were not shown because too many files have changed in this diff Show More