mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
Build the Virtual Console patch with make crystal11_vc
(#882)
Fixes #813
This commit is contained in:
parent
775b5d046c
commit
31c3c94d64
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -28,6 +28,9 @@
|
||||
*.attrmap 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
|
||||
*.lz binary diff=hex
|
||||
*.2bpp binary diff=hex
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,6 +17,7 @@ gfx/pokemon/*/frames.asm
|
||||
# compiled roms
|
||||
*.gbc
|
||||
*.gb
|
||||
*.patch
|
||||
|
||||
# rgbds extras
|
||||
*.map
|
||||
|
55
Makefile
55
Makefile
@ -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 := \
|
||||
audio.o \
|
||||
@ -23,6 +28,7 @@ pokecrystal11_obj := $(rom_obj:.o=11.o)
|
||||
pokecrystal_au_obj := $(rom_obj:.o=_au.o)
|
||||
pokecrystal_debug_obj := $(rom_obj:.o=_debug.o)
|
||||
pokecrystal11_debug_obj := $(rom_obj:.o=11_debug.o)
|
||||
pokecrystal11_vc_obj := $(rom_obj:.o=11_vc.o)
|
||||
|
||||
|
||||
### Build tools
|
||||
@ -54,16 +60,42 @@ crystal11: pokecrystal11.gbc
|
||||
crystal_au: pokecrystal_au.gbc
|
||||
crystal_debug: pokecrystal_debug.gbc
|
||||
crystal11_debug: pokecrystal11_debug.gbc
|
||||
crystal11_vc: pokecrystal11.patch
|
||||
|
||||
clean: tidy
|
||||
find gfx \( -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
|
||||
find gfx \
|
||||
\( -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:
|
||||
$(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/
|
||||
|
||||
compare: $(roms)
|
||||
compare: $(roms) $(patches)
|
||||
@$(SHA1) -c roms.sha1
|
||||
|
||||
tools:
|
||||
@ -81,6 +113,12 @@ $(pokecrystal11_obj): RGBASMFLAGS += -D _CRYSTAL11
|
||||
$(pokecrystal_au_obj): RGBASMFLAGS += -D _CRYSTAL11 -D _CRYSTAL_AU
|
||||
$(pokecrystal_debug_obj): RGBASMFLAGS += -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
|
||||
$(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_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_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
|
||||
|
||||
@ -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_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_vc_opt = -Cjv -t PM_CRYSTAL -i BYTE -n 1 -k 01 -l 0x33 -m 0x10 -r 3 -p 0
|
||||
|
||||
pokecrystal_base = us
|
||||
pokecrystal11_base = us
|
||||
pokecrystal_au_base = us
|
||||
pokecrystal11_vc_base = us
|
||||
pokecrystal_debug_base = dbg
|
||||
pokecrystal11_debug_base = dbg
|
||||
|
||||
|
@ -9,6 +9,7 @@ It builds the following ROMs:
|
||||
- Pokemon - Crystal Version (A) [C][!].gbc `sha1: a0fc810f1d4e124434f7be2c989ab5b5892ddf36`
|
||||
- CRYSTAL_ps3_010328d.bin `sha1: c60d57a24bbe8ecf7cba54ab3f90669f97bd330d`
|
||||
- CRYSTAL_ps3_us_revise_010710d.bin `sha1: 391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4`
|
||||
- CGBBYTE1.784.patch `sha1: a25517f60ca0e887d39ec698aa56a0040532a4b3`
|
||||
|
||||
To set up the repository, see [INSTALL.md](INSTALL.md).
|
||||
|
||||
|
@ -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)
|
||||
- [move_effect_commands.md](move_effect_commands.md)
|
||||
- [music_commands.md](music_commands.md)
|
||||
- [vc_patch.md](vc_patch.md)
|
||||
|
||||
|
||||
## Other subsystems
|
||||
|
124
docs/vc_patch.md
Normal file
124
docs/vc_patch.md
Normal 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`".
|
@ -21,6 +21,7 @@ DoBattleTransition:
|
||||
ld hl, hVBlank
|
||||
ld a, [hl]
|
||||
push af
|
||||
vc_hook FPA_link_fight_begin
|
||||
ld [hl], $1
|
||||
|
||||
.loop
|
||||
@ -58,6 +59,7 @@ DoBattleTransition:
|
||||
ld a, $1 ; unnecessary bankswitch?
|
||||
ldh [rSVBK], a
|
||||
pop af
|
||||
vc_hook FPA_link_fight_End4
|
||||
ldh [hVBlank], a
|
||||
call DelayFrame
|
||||
ret
|
||||
@ -310,6 +312,7 @@ StartTrainerBattle_Flash:
|
||||
dc 0, 0, 0, 1
|
||||
|
||||
StartTrainerBattle_SetUpForWavyOutro:
|
||||
vc_hook FPA_link_fight_End0
|
||||
farcall RespawnPlayerAndOpponent
|
||||
ld a, BANK(wLYOverrides)
|
||||
ldh [rSVBK], a
|
||||
@ -367,6 +370,7 @@ StartTrainerBattle_SineWave:
|
||||
ret
|
||||
|
||||
StartTrainerBattle_SetUpForSpinOutro:
|
||||
vc_hook FPA_link_fight_End1
|
||||
farcall RespawnPlayerAndOpponent
|
||||
ld a, BANK(wLYOverrides)
|
||||
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
|
||||
|
||||
StartTrainerBattle_SetUpForRandomScatterOutro:
|
||||
vc_hook FPA_link_fight_End2
|
||||
farcall RespawnPlayerAndOpponent
|
||||
ld a, BANK(wLYOverrides)
|
||||
ldh [rSVBK], a
|
||||
@ -763,6 +768,7 @@ StartTrainerBattle_DrawSineWave:
|
||||
calc_sine_wave
|
||||
|
||||
StartTrainerBattle_ZoomToBlack:
|
||||
vc_hook FPA_link_fight_End3
|
||||
farcall RespawnPlayerAndOpponent
|
||||
ld de, .boxes
|
||||
|
||||
|
@ -8940,6 +8940,7 @@ InitBattleDisplay:
|
||||
predef PlaceGraphic
|
||||
xor a
|
||||
ldh [hWY], a
|
||||
vc_hook fight_begin
|
||||
ldh [rWY], a
|
||||
call WaitBGMap
|
||||
call HideSprites
|
||||
|
@ -58,12 +58,20 @@ BattleAnimRunScript:
|
||||
farcall CheckBattleScene
|
||||
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 RunBattleAnimScript
|
||||
|
||||
call BattleAnimAssignPals
|
||||
call BattleAnimRequestPals
|
||||
|
||||
vc_hook FPA_001_End
|
||||
xor a
|
||||
ldh [hSCX], a
|
||||
ldh [hSCY], a
|
||||
@ -673,6 +681,7 @@ BattleAnimCmd_5GFX:
|
||||
.loop
|
||||
ld a, [wBattleAnimGFXTempTileID]
|
||||
cp (vTiles1 - vTiles0) / LEN_2BPP_TILE - BATTLEANIM_BASE_TILE
|
||||
vc_hook FPA_042801_Begin
|
||||
ret nc
|
||||
call GetBattleAnimByte
|
||||
ld [hli], a
|
||||
|
@ -74,7 +74,13 @@ _UnownPrinter:
|
||||
jr nz, .pressed_b
|
||||
|
||||
ldh a, [hJoyPressed]
|
||||
vc_patch print_forbid_1
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
and 0
|
||||
else
|
||||
and A_BUTTON
|
||||
endc
|
||||
vc_patch_end
|
||||
jr nz, .pressed_a
|
||||
|
||||
call .LeftRight
|
||||
|
@ -1033,6 +1033,7 @@ endr
|
||||
.FinalPush:
|
||||
ld hl, MltReq1Packet
|
||||
call _PushSGBPals
|
||||
vc_hook Network_RESET
|
||||
jp SGBDelayCycles
|
||||
|
||||
SGBBorder_PushBGPals:
|
||||
|
@ -67,7 +67,13 @@ Gen2ToGen1LinkComms:
|
||||
.player_1
|
||||
ld de, MUSIC_NONE
|
||||
call PlayMusic
|
||||
vc_patch NetworkDelay1
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld c, 26
|
||||
else
|
||||
ld c, 3
|
||||
endc
|
||||
vc_patch_end
|
||||
call DelayFrames
|
||||
xor a
|
||||
ldh [rIF], a
|
||||
@ -77,6 +83,7 @@ Gen2ToGen1LinkComms:
|
||||
ld hl, wLinkBattleRNPreamble
|
||||
ld de, wEnemyMon
|
||||
ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
|
||||
vc_hook Network358
|
||||
call Serial_ExchangeBytes
|
||||
ld a, SERIAL_NO_DATA_BYTE
|
||||
ld [de], a
|
||||
@ -84,6 +91,7 @@ Gen2ToGen1LinkComms:
|
||||
ld hl, wLinkData
|
||||
ld de, wOTPartyData
|
||||
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
|
||||
ld a, SERIAL_NO_DATA_BYTE
|
||||
ld [de], a
|
||||
@ -91,6 +99,7 @@ Gen2ToGen1LinkComms:
|
||||
ld hl, wPlayerPatchLists
|
||||
ld de, wOTPatchLists
|
||||
ld bc, 200
|
||||
vc_hook Network364
|
||||
call Serial_ExchangeBytes
|
||||
|
||||
xor a
|
||||
@ -224,7 +233,13 @@ Gen2ToGen2LinkComms:
|
||||
.player_1
|
||||
ld de, MUSIC_NONE
|
||||
call PlayMusic
|
||||
vc_patch NetworkDelay4
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld c, 26
|
||||
else
|
||||
ld c, 3
|
||||
endc
|
||||
vc_patch_end
|
||||
call DelayFrames
|
||||
xor a
|
||||
ldh [rIF], a
|
||||
@ -234,6 +249,7 @@ Gen2ToGen2LinkComms:
|
||||
ld hl, wLinkBattleRNPreamble
|
||||
ld de, wEnemyMon
|
||||
ld bc, SERIAL_RN_PREAMBLE_LENGTH + SERIAL_RNS_LENGTH
|
||||
vc_hook Network360
|
||||
call Serial_ExchangeBytes
|
||||
ld a, SERIAL_NO_DATA_BYTE
|
||||
ld [de], a
|
||||
@ -241,6 +257,7 @@ Gen2ToGen2LinkComms:
|
||||
ld hl, wLinkData
|
||||
ld de, wOTPartyData
|
||||
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
|
||||
ld a, SERIAL_NO_DATA_BYTE
|
||||
ld [de], a
|
||||
@ -248,6 +265,7 @@ Gen2ToGen2LinkComms:
|
||||
ld hl, wPlayerPatchLists
|
||||
ld de, wOTPatchLists
|
||||
ld bc, 200
|
||||
vc_hook Network362
|
||||
call Serial_ExchangeBytes
|
||||
|
||||
ld a, [wLinkMode]
|
||||
@ -256,6 +274,7 @@ Gen2ToGen2LinkComms:
|
||||
ld hl, wLinkPlayerMail
|
||||
ld de, wLinkOTMail
|
||||
ld bc, wLinkPlayerMailEnd - wLinkPlayerMail
|
||||
vc_hook Network363
|
||||
call ExchangeBytes
|
||||
|
||||
.not_trading
|
||||
@ -1608,6 +1627,7 @@ ExitLinkCommunications:
|
||||
ldh [rSC], a
|
||||
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
|
||||
ldh [rSC], a
|
||||
vc_hook ret_heya
|
||||
ret
|
||||
|
||||
GSPlaceTradeScreenFooter: ; unreferenced
|
||||
@ -2009,6 +2029,7 @@ LinkTrade:
|
||||
ld de, String_TradeCompleted
|
||||
call PlaceString
|
||||
farcall Link_WaitBGMap
|
||||
vc_hook save_game_end
|
||||
ld c, 50
|
||||
call DelayFrames
|
||||
ld a, [wLinkMode]
|
||||
@ -2161,7 +2182,13 @@ GetIncompatibleMonName:
|
||||
ret
|
||||
|
||||
EnterTimeCapsule:
|
||||
vc_patch NetworkDelay2
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld c, 26
|
||||
else
|
||||
ld c, 10
|
||||
endc
|
||||
vc_patch_end
|
||||
call DelayFrames
|
||||
ld a, $4
|
||||
call Link_EnsureSync
|
||||
@ -2218,6 +2245,7 @@ WaitForOtherPlayerToExit:
|
||||
ld [hl], a
|
||||
ldh [hVBlank], a
|
||||
ld [wLinkMode], a
|
||||
vc_hook term_exit
|
||||
ret
|
||||
|
||||
SetBitsForLinkTradeRequest:
|
||||
@ -2282,6 +2310,7 @@ WaitForLinkedFriend:
|
||||
ld a, (0 << rSC_ON) | (0 << rSC_CLOCK)
|
||||
ldh [rSC], a
|
||||
ld a, (1 << rSC_ON) | (0 << rSC_CLOCK)
|
||||
vc_hook linkCable_fake_begin
|
||||
ldh [rSC], a
|
||||
ld a, [wLinkTimeoutFrames]
|
||||
dec a
|
||||
@ -2374,7 +2403,13 @@ CheckLinkTimeout_Gen2:
|
||||
ld a, $6
|
||||
ld [wPlayerLinkAction], a
|
||||
ld hl, wLinkTimeoutFrames
|
||||
vc_patch NetworkDelay6
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld a, $3
|
||||
else
|
||||
ld a, 1
|
||||
endc
|
||||
vc_patch_end
|
||||
ld [hli], a
|
||||
ld [hl], 50
|
||||
call Link_CheckCommunicationError
|
||||
@ -2395,6 +2430,7 @@ CheckLinkTimeout_Gen2:
|
||||
Link_CheckCommunicationError:
|
||||
xor a
|
||||
ldh [hSerialReceivedNewData], a
|
||||
vc_hook linkCable_fake_end
|
||||
ld a, [wLinkTimeoutFrames]
|
||||
ld h, a
|
||||
ld a, [wLinkTimeoutFrames + 1]
|
||||
@ -2425,6 +2461,7 @@ Link_CheckCommunicationError:
|
||||
.CheckConnected:
|
||||
call WaitLinkTransfer
|
||||
ld hl, wLinkTimeoutFrames
|
||||
vc_hook Network_RECHECK
|
||||
ld a, [hli]
|
||||
inc a
|
||||
ret nz
|
||||
@ -2433,7 +2470,13 @@ Link_CheckCommunicationError:
|
||||
ret
|
||||
|
||||
.AcknowledgeSerial:
|
||||
vc_patch NetworkDelay3
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld b, 26
|
||||
else
|
||||
ld b, 10
|
||||
endc
|
||||
vc_patch_end
|
||||
.loop
|
||||
call DelayFrame
|
||||
call LinkDataReceived
|
||||
@ -2460,8 +2503,10 @@ TryQuickSave:
|
||||
ld a, [wChosenCableClubRoom]
|
||||
push af
|
||||
farcall Link_SaveGame
|
||||
vc_hook linkCable_block_input
|
||||
ld a, TRUE
|
||||
jr nc, .return_result
|
||||
vc_hook linkCable_block_input2
|
||||
xor a ; FALSE
|
||||
.return_result
|
||||
ld [wScriptVar], a
|
||||
@ -2498,6 +2543,7 @@ CheckBothSelectedSameRoom:
|
||||
ret
|
||||
|
||||
TimeCapsule:
|
||||
vc_hook to_play2_mons1
|
||||
ld a, LINK_TIMECAPSULE
|
||||
ld [wLinkMode], a
|
||||
call DisableSpriteUpdates
|
||||
@ -2508,6 +2554,7 @@ TimeCapsule:
|
||||
ret
|
||||
|
||||
TradeCenter:
|
||||
vc_hook to_play2_trade
|
||||
ld a, LINK_TRADECENTER
|
||||
ld [wLinkMode], a
|
||||
call DisableSpriteUpdates
|
||||
@ -2518,6 +2565,7 @@ TradeCenter:
|
||||
ret
|
||||
|
||||
Colosseum:
|
||||
vc_hook to_play2_battle
|
||||
ld a, LINK_COLOSSEUM
|
||||
ld [wLinkMode], a
|
||||
call DisableSpriteUpdates
|
||||
@ -2532,6 +2580,7 @@ CloseLink:
|
||||
ld [wLinkMode], a
|
||||
ld c, 3
|
||||
call DelayFrames
|
||||
vc_hook room_check
|
||||
jp Link_ResetSerialRegistersAfterLinkClosure
|
||||
|
||||
FailedLinkToPast:
|
||||
|
@ -37,14 +37,23 @@ DoMysteryGift:
|
||||
; Prepare the first of two messages for wMysteryGiftPartnerData
|
||||
farcall StageDataForMysteryGift
|
||||
call ClearMysteryGiftTrainer
|
||||
vc_patch infrared_fake_0
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
farcall StagePartyDataForMysteryGift
|
||||
call ClearMysteryGiftTrainer
|
||||
nop
|
||||
else
|
||||
ld a, 2
|
||||
ld [wMysteryGiftMessageCount], a
|
||||
ld a, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
|
||||
ld [wMysteryGiftStagedDataLength], a
|
||||
endc
|
||||
vc_patch_end
|
||||
|
||||
ldh a, [rIE]
|
||||
push af
|
||||
call ExchangeMysteryGiftData
|
||||
vc_hook infrared_fake_4
|
||||
ld d, a
|
||||
xor a
|
||||
ldh [rIF], a
|
||||
@ -260,6 +269,26 @@ DoMysteryGift:
|
||||
jp CloseSRAM
|
||||
|
||||
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
|
||||
farcall ClearChannels
|
||||
call InitializeIRCommunicationInterrupts
|
||||
@ -268,6 +297,8 @@ ExchangeMysteryGiftData:
|
||||
call BeginIRCommunication
|
||||
call InitializeIRCommunicationRoles
|
||||
ldh a, [hMGStatusFlags]
|
||||
endc
|
||||
vc_patch_end
|
||||
cp MG_CANCELED
|
||||
jp z, EndOrContinueMysteryGiftIRCommunication
|
||||
cp MG_OKAY
|
||||
|
@ -362,7 +362,9 @@ Menu_WasButtonPressed:
|
||||
call GetMenuJoypad
|
||||
and a
|
||||
ret z
|
||||
vc_hook print_forbid_3
|
||||
scf
|
||||
vc_hook print_forbid_2
|
||||
ret
|
||||
|
||||
_2DMenuInterpretJoypad:
|
||||
|
@ -161,6 +161,15 @@ AddHallOfFameEntry:
|
||||
ld bc, wHallOfFamePokemonListEnd - wHallOfFamePokemonList + 1
|
||||
call CopyBytes
|
||||
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
|
||||
|
||||
SaveGameData:
|
||||
|
@ -389,6 +389,7 @@ Script_yesorno:
|
||||
ld a, TRUE
|
||||
.no
|
||||
ld [wScriptVar], a
|
||||
vc_hook E_YESNO
|
||||
ret
|
||||
|
||||
Script_loadmenu:
|
||||
|
@ -356,6 +356,7 @@ Pokedex_UpdateDexEntryScreen:
|
||||
ld a, [hl]
|
||||
and B_BUTTON
|
||||
jr nz, .return_to_prev_screen
|
||||
vc_hook print_forbid_5
|
||||
ld a, [hl]
|
||||
and A_BUTTON
|
||||
jr nz, .do_menu_action
|
||||
|
@ -67,7 +67,13 @@ ReadAnyMail:
|
||||
ldh a, [hJoyPressed]
|
||||
and A_BUTTON | B_BUTTON | START
|
||||
jr z, .loop
|
||||
vc_patch print_forbid_4
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
and 0
|
||||
else
|
||||
and START
|
||||
endc
|
||||
vc_patch_end
|
||||
jr nz, .pressed_start
|
||||
ret
|
||||
|
||||
|
@ -290,6 +290,7 @@ Serial_SyncAndExchangeNybble:: ; unreferenced
|
||||
jp WaitLinkTransfer ; pointless
|
||||
|
||||
WaitLinkTransfer::
|
||||
vc_hook send_send_buf2
|
||||
ld a, $ff
|
||||
ld [wOtherPlayerLinkAction], a
|
||||
.loop
|
||||
@ -317,14 +318,26 @@ WaitLinkTransfer::
|
||||
inc a
|
||||
jr z, .loop
|
||||
|
||||
vc_patch Network10
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld b, 26
|
||||
else
|
||||
ld b, 10
|
||||
endc
|
||||
vc_patch_end
|
||||
.receive
|
||||
call DelayFrame
|
||||
call LinkTransfer
|
||||
dec b
|
||||
jr nz, .receive
|
||||
|
||||
vc_patch Network11
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld b, 26
|
||||
else
|
||||
ld b, 10
|
||||
endc
|
||||
vc_patch_end
|
||||
.acknowledge
|
||||
call DelayFrame
|
||||
call LinkDataReceived
|
||||
@ -333,6 +346,7 @@ WaitLinkTransfer::
|
||||
|
||||
ld a, [wOtherPlayerLinkAction]
|
||||
ld [wOtherPlayerLinkMode], a
|
||||
vc_hook send_send_buf2_ret
|
||||
ret
|
||||
|
||||
LinkTransfer::
|
||||
|
@ -6,6 +6,7 @@ INCLUDE "macros/data.asm"
|
||||
INCLUDE "macros/code.asm"
|
||||
INCLUDE "macros/gfx.asm"
|
||||
INCLUDE "macros/coords.asm"
|
||||
INCLUDE "macros/vc.asm"
|
||||
|
||||
INCLUDE "macros/scripts/audio.asm"
|
||||
INCLUDE "macros/scripts/maps.asm"
|
||||
|
27
macros/vc.asm
Normal file
27
macros/vc.asm
Normal file
@ -0,0 +1,27 @@
|
||||
vc_hook: MACRO
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
.VC_\1::
|
||||
endc
|
||||
ENDM
|
||||
|
||||
vc_patch: MACRO
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
assert !DEF(CURRENT_VC_PATCH), "Already started a vc_patch"
|
||||
CURRENT_VC_PATCH EQUS "\1"
|
||||
.VC_{CURRENT_VC_PATCH}::
|
||||
endc
|
||||
ENDM
|
||||
|
||||
vc_patch_end: MACRO
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
assert DEF(CURRENT_VC_PATCH), "No vc_patch started"
|
||||
.VC_{CURRENT_VC_PATCH}_End::
|
||||
PURGE CURRENT_VC_PATCH
|
||||
endc
|
||||
ENDM
|
||||
|
||||
vc_assert: MACRO
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
assert \#
|
||||
endc
|
||||
ENDM
|
@ -1530,6 +1530,7 @@ Function1009f3:
|
||||
_LinkBattleSendReceiveAction:
|
||||
call .StageForSend
|
||||
ld [wLinkBattleSentAction], a
|
||||
vc_hook send_byt2
|
||||
farcall PlaceWaitingText
|
||||
ld a, [wLinkMode]
|
||||
cp LINK_MOBILE
|
||||
@ -1584,20 +1585,35 @@ _LinkBattleSendReceiveAction:
|
||||
inc a
|
||||
jr z, .waiting
|
||||
|
||||
vc_hook send_byt2_ret
|
||||
vc_patch send_byt2_wait
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld b, 26
|
||||
else
|
||||
ld b, 10
|
||||
endc
|
||||
vc_patch_end
|
||||
.receive
|
||||
call DelayFrame
|
||||
call LinkTransfer
|
||||
dec b
|
||||
jr nz, .receive
|
||||
|
||||
vc_hook send_dummy
|
||||
vc_patch send_dummy_wait
|
||||
if DEF(_CRYSTAL11_VC)
|
||||
ld b, 26
|
||||
else
|
||||
ld b, 10
|
||||
endc
|
||||
vc_patch_end
|
||||
.acknowledge
|
||||
call DelayFrame
|
||||
call LinkDataReceived
|
||||
dec b
|
||||
jr nz, .acknowledge
|
||||
|
||||
vc_hook send_dummy_end
|
||||
ld a, [wOtherPlayerLinkAction]
|
||||
ld [wBattleAction], a
|
||||
ret
|
||||
|
@ -3,3 +3,4 @@ f2f52230b536214ef7c9924f483392993e226cfb *pokecrystal11.gbc
|
||||
a0fc810f1d4e124434f7be2c989ab5b5892ddf36 *pokecrystal_au.gbc
|
||||
c60d57a24bbe8ecf7cba54ab3f90669f97bd330d *pokecrystal_debug.gbc
|
||||
391ae86b1d5a26db712ffe6c28bbf2a1f804c3c4 *pokecrystal11_debug.gbc
|
||||
a25517f60ca0e887d39ec698aa56a0040532a4b3 *pokecrystal11.patch
|
||||
|
7
tools/.gitignore
vendored
7
tools/.gitignore
vendored
@ -1,8 +1,9 @@
|
||||
gfx
|
||||
lzcomp
|
||||
png_dimensions
|
||||
scan_includes
|
||||
make_patch
|
||||
palette
|
||||
png_dimensions
|
||||
pokemon_animation
|
||||
pokemon_animation_graphics
|
||||
gfx
|
||||
scan_includes
|
||||
stadium
|
||||
|
@ -6,6 +6,7 @@ CFLAGS := -O3 -std=c11 -Wall -Wextra -pedantic -Wno-missing-field-initializers
|
||||
tools := \
|
||||
lzcomp \
|
||||
gfx \
|
||||
make_patch \
|
||||
png_dimensions \
|
||||
pokemon_animation \
|
||||
pokemon_animation_graphics \
|
||||
|
434
tools/make_patch.c
Normal file
434
tools/make_patch.c
Normal file
@ -0,0 +1,434 @@
|
||||
#define PROGRAM_NAME "make_patch"
|
||||
#define USAGE_OPTS "labels.sym constants.sym patched.gbc original.gbc vc.patch.template vc.patch"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
struct Buffer {
|
||||
size_t item_size;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
struct Symbol *next;
|
||||
unsigned int address;
|
||||
unsigned int offset;
|
||||
char name[]; // C99 FAM
|
||||
};
|
||||
|
||||
struct Patch {
|
||||
unsigned int offset;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct Buffer *buffer_create(size_t item_size) {
|
||||
struct Buffer *buffer = xmalloc(sizeof(*buffer));
|
||||
buffer->item_size = item_size;
|
||||
buffer->size = 0;
|
||||
buffer->capacity = 0x10;
|
||||
buffer->data = xmalloc(buffer->capacity * item_size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void buffer_append(struct Buffer *buffer, const void *item) {
|
||||
if (buffer->size >= buffer->capacity) {
|
||||
buffer->capacity = (buffer->capacity + 1) * 2;
|
||||
buffer->data = xrealloc(buffer->data, buffer->capacity * buffer->item_size);
|
||||
}
|
||||
memcpy((char *)buffer->data + (buffer->size++ * buffer->item_size), item, buffer->item_size);
|
||||
}
|
||||
|
||||
void buffer_free(struct Buffer *buffer) {
|
||||
free(buffer->data);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void symbol_append(struct Symbol **symbols, const char *name, int bank, int address) {
|
||||
size_t name_len = strlen(name) + 1;
|
||||
struct Symbol *symbol = xmalloc(sizeof(*symbol) + name_len);
|
||||
symbol->address = address;
|
||||
symbol->offset = bank > 0 && address < 0x8000 ? address + (bank - 1) * 0x4000 : address;
|
||||
memcpy(symbol->name, name, name_len);
|
||||
symbol->next = *symbols;
|
||||
*symbols = symbol;
|
||||
}
|
||||
|
||||
void symbol_free(struct Symbol *symbols) {
|
||||
for (struct Symbol *next; symbols; symbols = next) {
|
||||
next = symbols->next;
|
||||
free(symbols);
|
||||
}
|
||||
}
|
||||
|
||||
const struct Symbol *symbol_find(const struct Symbol *symbols, const char *name) {
|
||||
size_t name_len = strlen(name);
|
||||
for (const struct Symbol *symbol = symbols; symbol; symbol = symbol->next) {
|
||||
size_t sym_name_len = strlen(symbol->name);
|
||||
if (name_len > sym_name_len) {
|
||||
continue;
|
||||
}
|
||||
const char *sym_name = symbol->name;
|
||||
if (name[0] == '.') {
|
||||
// If `name` is a local label, compare it to the local part of `symbol->name`
|
||||
sym_name += sym_name_len - name_len;
|
||||
}
|
||||
if (!strcmp(sym_name, name)) {
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
error_exit("Error: Unknown symbol: \"%s\"\n", name);
|
||||
}
|
||||
|
||||
const struct Symbol *symbol_find_cat(const struct Symbol *symbols, const char *prefix, const char *suffix) {
|
||||
char *sym_name = xmalloc(strlen(prefix) + strlen(suffix) + 1);
|
||||
sprintf(sym_name, "%s%s", prefix, suffix);
|
||||
const struct Symbol *symbol = symbol_find(symbols, sym_name);
|
||||
free(sym_name);
|
||||
return symbol;
|
||||
}
|
||||
|
||||
int parse_number(const char *input, int base) {
|
||||
char *endptr;
|
||||
int n = (int)strtol(input, &endptr, base);
|
||||
if (endptr == input || *endptr || n < 0) {
|
||||
error_exit("Error: Cannot parse number: \"%s\"", input);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
void parse_symbol_value(char *input, int *restrict bank, int *restrict address) {
|
||||
char *colon = strchr(input, ':');
|
||||
if (!colon) {
|
||||
error_exit("Error: Cannot parse bank+address: \"%s\"", input);
|
||||
}
|
||||
*colon++ = '\0';
|
||||
*bank = parse_number(input, 16);
|
||||
*address = parse_number(colon, 16);
|
||||
}
|
||||
|
||||
void parse_symbols(const char *filename, struct Symbol **symbols) {
|
||||
FILE *file = xfopen(filename, 'r');
|
||||
struct Buffer *buffer = buffer_create(1);
|
||||
|
||||
enum { SYM_PRE, SYM_VALUE, SYM_SPACE, SYM_NAME } state = SYM_PRE;
|
||||
int bank = 0;
|
||||
int address = 0;
|
||||
|
||||
for (;;) {
|
||||
int c = getc(file);
|
||||
if (c == EOF || c == '\n' || c == '\r' || c == ';' || (state == SYM_NAME && (c == ' ' || c == '\t'))) {
|
||||
if (state == SYM_NAME) {
|
||||
// The symbol name has ended; append the buffered symbol
|
||||
buffer_append(buffer, &(char []){'\0'});
|
||||
symbol_append(symbols, buffer->data, bank, address);
|
||||
}
|
||||
// Skip to the next line, ignoring anything after the symbol value and name
|
||||
state = SYM_PRE;
|
||||
while (c != EOF && c != '\n' && c != '\r') {
|
||||
c = getc(file);
|
||||
}
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
} else if (c != ' ' && c != '\t') {
|
||||
if (state == SYM_PRE || state == SYM_SPACE) {
|
||||
// The symbol value or name has started; buffer its contents
|
||||
if (++state == SYM_NAME) {
|
||||
// The symbol name has started; parse the buffered value
|
||||
buffer_append(buffer, &(char []){'\0'});
|
||||
parse_symbol_value(buffer->data, &bank, &address);
|
||||
}
|
||||
buffer->size = 0;
|
||||
}
|
||||
buffer_append(buffer, &c);
|
||||
} else if (state == SYM_VALUE) {
|
||||
// The symbol value has ended; wait to see if a name comes after it
|
||||
state = SYM_SPACE;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
buffer_free(buffer);
|
||||
}
|
||||
|
||||
int parse_arg_value(const char *arg, bool absolute, const struct Symbol *symbols, const char *patch_name) {
|
||||
// Comparison operators for "ConditionValueB" evaluate to their particular values
|
||||
static const char *comparisons[] = {"==", ">", "<", ">=", "<=", "!=", "||"};
|
||||
for (unsigned int i = 0; i < sizeof(comparisons) / sizeof(*comparisons); i++) {
|
||||
if (!strcmp(arg, comparisons[i])) {
|
||||
return i == 6 ? 0x11 : i; // "||" is 0x11
|
||||
}
|
||||
}
|
||||
|
||||
// Literal numbers evaluate to themselves
|
||||
if (isdigit((unsigned)arg[0]) || arg[0] == '+') {
|
||||
return parse_number(arg, 0);
|
||||
}
|
||||
|
||||
// Symbols evaluate to their offset or address, plus an optional offset mod
|
||||
int offset_mod = 0;
|
||||
char *plus = strchr(arg, '+');
|
||||
if (plus) {
|
||||
offset_mod = parse_number(plus, 0);
|
||||
*plus = '\0';
|
||||
}
|
||||
const char *sym_name = !strcmp(arg, "@") ? patch_name : arg; // "@" is the current patch label
|
||||
const struct Symbol *symbol = symbol_find(symbols, sym_name);
|
||||
return (absolute ? symbol->offset : symbol->address) + offset_mod;
|
||||
}
|
||||
|
||||
void interpret_command(char *command, const struct Symbol *current_hook, const struct Symbol *symbols, struct Buffer *patches, FILE *restrict new_rom, FILE *restrict orig_rom, FILE *restrict output) {
|
||||
// Strip all leading spaces and all but one trailing space
|
||||
int x = 0;
|
||||
for (int i = 0; command[i]; i++) {
|
||||
if (!isspace((unsigned)command[i]) || (i > 0 && !isspace((unsigned)command[i - 1]))) {
|
||||
command[x++] = command[i];
|
||||
}
|
||||
}
|
||||
command[x - (x > 0 && isspace((unsigned)command[x - 1]))] = '\0';
|
||||
|
||||
// Count the arguments
|
||||
int argc = 0;
|
||||
for (const char *c = command; *c; c++) {
|
||||
if (isspace((unsigned)*c)) {
|
||||
argc++;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the arguments
|
||||
char *argv[argc]; // VLA
|
||||
char *arg = command;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
while (*arg && !isspace((unsigned)*arg)) {
|
||||
arg++;
|
||||
}
|
||||
if (!*arg) {
|
||||
break;
|
||||
}
|
||||
*arg++ = '\0';
|
||||
argv[i] = arg;
|
||||
}
|
||||
|
||||
// Use the arguments
|
||||
if (!strcmp(command, "patch") || !strcmp(command, "PATCH") || !strcmp(command, "patch_") || !strcmp(command, "PATCH_")) {
|
||||
if (!current_hook) {
|
||||
error_exit("Error: No current patch for command: \"%s\"", command);
|
||||
}
|
||||
int current_offset = current_hook->offset + (argc > 0 ? parse_number(argv[0], 0) : 0);
|
||||
if (fseek(orig_rom, current_offset, SEEK_SET)) {
|
||||
error_exit("Error: Cannot seek to \"vc_patch %s\" in the original ROM\n", current_hook->name);
|
||||
}
|
||||
if (fseek(new_rom, current_offset, SEEK_SET)) {
|
||||
error_exit("Error: Cannot seek to \"vc_patch %s\" in the new ROM\n", current_hook->name);
|
||||
}
|
||||
const struct Symbol *current_hook_end = symbol_find_cat(symbols, current_hook->name, "_End");
|
||||
int length = current_hook_end->offset - current_offset;
|
||||
buffer_append(patches, &(struct Patch){current_offset, length});
|
||||
bool modified = false;
|
||||
if (length == 1) {
|
||||
int c = getc(new_rom);
|
||||
modified = c != getc(orig_rom);
|
||||
fprintf(output, isupper((unsigned)command[0]) ? "0x%02X" : "0x%02x", c);
|
||||
} else {
|
||||
fprintf(output, command[strlen(command) - 1] == '_' ? "a%d: " : "a%d:", length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i) {
|
||||
putc(' ', output);
|
||||
}
|
||||
int c = getc(new_rom);
|
||||
modified |= c != getc(orig_rom);
|
||||
fprintf(output, isupper((unsigned)command[0]) ? "%02X" : "%02x", c);
|
||||
}
|
||||
}
|
||||
if (!modified) {
|
||||
fprintf(stderr, PROGRAM_NAME ": Warning: \"vc_patch %s\" doesn't alter the ROM\n", current_hook->name);
|
||||
}
|
||||
|
||||
} else if (!strcmp(command, "dws") || !strcmp(command, "DWS") || !strcmp(command, "dws_") || !strcmp(command, "DWS_")) {
|
||||
if (argc < 1) {
|
||||
error_exit("Error: Invalid arguments for command: \"%s\"", command);
|
||||
}
|
||||
fprintf(output, command[strlen(command) - 1] == '_' ? "a%d: " : "a%d:", argc * 2);
|
||||
for (int i = 0; i < argc; i++) {
|
||||
int value = parse_arg_value(argv[i], false, symbols, current_hook->name);
|
||||
if (value > 0xffff) {
|
||||
error_exit("Error: Invalid value for \"%s\" argument: 0x%x", command, value);
|
||||
}
|
||||
if (i) {
|
||||
putc(' ', output);
|
||||
}
|
||||
fprintf(output, isupper((unsigned)command[0]) ? "%02X %02X": "%02x %02x", value & 0xff, value >> 8);
|
||||
}
|
||||
|
||||
} else if (!strcmp(command, "db") || !strcmp(command, "DB") || !strcmp(command, "db_") || !strcmp(command, "DB_")) {
|
||||
if (argc != 1) {
|
||||
error_exit("Error: Invalid arguments for command: \"%s\"", command);
|
||||
}
|
||||
int value = parse_arg_value(argv[0], false, symbols, current_hook->name);
|
||||
if (value > 0xff) {
|
||||
error_exit("Error: Invalid value for \"%s\" argument: 0x%x", command, value);
|
||||
}
|
||||
fputs(command[strlen(command) - 1] == '_' ? "a1: " : "a1:", output);
|
||||
fprintf(output, isupper((unsigned)command[0]) ? "%02X" : "%02x", value);
|
||||
|
||||
} else if (!strcmp(command, "hex") || !strcmp(command, "HEX") || !strcmp(command, "HEx") || !strcmp(command, "Hex") || !strcmp(command, "heX") || !strcmp(command, "hEX")) {
|
||||
if (argc != 1 && argc != 2) {
|
||||
error_exit("Error: Invalid arguments for command: \"%s\"", command);
|
||||
}
|
||||
int value = parse_arg_value(argv[0], true, symbols, current_hook->name);
|
||||
int padding = argc > 1 ? parse_number(argv[1], 0) : 2;
|
||||
if (!strcmp(command, "HEx")) {
|
||||
fprintf(output, "0x%0*X%02x", padding - 2, value >> 8, value & 0xff);
|
||||
} else if (!strcmp(command, "Hex")) {
|
||||
fprintf(output, "0x%0*X%03x", padding - 3, value >> 12, value & 0xfff);
|
||||
} else if (!strcmp(command, "heX")) {
|
||||
fprintf(output, "0x%0*x%02X", padding - 2, value >> 8, value & 0xff);
|
||||
} else if (!strcmp(command, "hEX")) {
|
||||
fprintf(output, "0x%0*x%03X", padding - 3, value >> 12, value & 0xfff);
|
||||
} else {
|
||||
fprintf(output, isupper((unsigned)command[0]) ? "0x%0*X" : "0x%0*x", padding, value);
|
||||
}
|
||||
|
||||
} else {
|
||||
error_exit("Error: Unknown command: \"%s\"\n", command);
|
||||
}
|
||||
}
|
||||
|
||||
void skip_to_next_line(FILE *restrict input, FILE *restrict output) {
|
||||
for (int c = getc(input); c != EOF; c = getc(input)) {
|
||||
putc(c, output);
|
||||
if (c == '\n' || c == '\r') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Buffer *process_template(const char *template_filename, const char *patch_filename, FILE *restrict new_rom, FILE *restrict orig_rom, const struct Symbol *symbols) {
|
||||
FILE *input = xfopen(template_filename, 'r');
|
||||
FILE *output = xfopen(patch_filename, 'w');
|
||||
|
||||
struct Buffer *patches = buffer_create(sizeof(struct Patch));
|
||||
struct Buffer *buffer = buffer_create(1);
|
||||
|
||||
// The ROM checksum will always differ
|
||||
buffer_append(patches, &(struct Patch){0x14e, 2});
|
||||
// The Stadium data (see stadium.c) will always differ
|
||||
unsigned int rom_size = (unsigned int)xfsize("", orig_rom);
|
||||
unsigned int stadium_size = 24 + 6 + 2 + (rom_size / 0x2000) * 2;
|
||||
buffer_append(patches, &(struct Patch){rom_size - stadium_size, stadium_size});
|
||||
|
||||
// Fill in the template
|
||||
const struct Symbol *current_hook = NULL;
|
||||
for (int c = getc(input); c != EOF; c = getc(input)) {
|
||||
switch (c) {
|
||||
case ';':
|
||||
// ";" comments until the end of the line
|
||||
putc(c, output);
|
||||
skip_to_next_line(input, output);
|
||||
break;
|
||||
|
||||
case '{':
|
||||
// "{...}" is a template command; buffer its contents
|
||||
buffer->size = 0;
|
||||
for (c = getc(input); c != EOF && c != '}'; c = getc(input)) {
|
||||
buffer_append(buffer, &c);
|
||||
}
|
||||
buffer_append(buffer, &(char []){'\0'});
|
||||
// Interpret the command in the context of the current patch
|
||||
interpret_command(buffer->data, current_hook, symbols, patches, new_rom, orig_rom, output);
|
||||
break;
|
||||
|
||||
case '[':
|
||||
// "[...]" is a patch label; buffer its contents
|
||||
putc(c, output);
|
||||
buffer->size = 0;
|
||||
for (c = getc(input); c != EOF; c = getc(input)) {
|
||||
putc(c, output);
|
||||
if (c == ']') {
|
||||
break;
|
||||
} else if (!isalnum(c) && c != '_' && c != '@' && c != '#') {
|
||||
// Convert non-identifier characters to underscores
|
||||
c = '_';
|
||||
}
|
||||
buffer_append(buffer, &c);
|
||||
}
|
||||
buffer_append(buffer, &(char []){'\0'});
|
||||
// The current patch should have a corresponding ".VC_" label
|
||||
current_hook = symbol_find_cat(symbols, ".VC_", buffer->data);
|
||||
skip_to_next_line(input, output);
|
||||
break;
|
||||
|
||||
default:
|
||||
putc(c, output);
|
||||
}
|
||||
}
|
||||
|
||||
rewind(orig_rom);
|
||||
rewind(new_rom);
|
||||
|
||||
fclose(input);
|
||||
fclose(output);
|
||||
buffer_free(buffer);
|
||||
return patches;
|
||||
}
|
||||
|
||||
int compare_patch(const void *patch1, const void *patch2) {
|
||||
unsigned int offset1 = ((const struct Patch *)patch1)->offset;
|
||||
unsigned int offset2 = ((const struct Patch *)patch2)->offset;
|
||||
return offset1 > offset2 ? 1 : offset1 < offset2 ? -1 : 0;
|
||||
}
|
||||
|
||||
bool verify_completeness(FILE *restrict orig_rom, FILE *restrict new_rom, struct Buffer *patches) {
|
||||
qsort(patches->data, patches->size, patches->item_size, compare_patch);
|
||||
for (unsigned int offset = 0, index = 0; ; offset++) {
|
||||
int orig_byte = getc(orig_rom);
|
||||
int new_byte = getc(new_rom);
|
||||
if (orig_byte == EOF || new_byte == EOF) {
|
||||
return orig_byte == new_byte;
|
||||
}
|
||||
struct Patch *patch = &((struct Patch *)patches->data)[index];
|
||||
if (index < patches->size && patch->offset == offset) {
|
||||
if (fseek(orig_rom, patch->size, SEEK_CUR)) {
|
||||
return false;
|
||||
}
|
||||
if (fseek(new_rom, patch->size, SEEK_CUR)) {
|
||||
return false;
|
||||
}
|
||||
offset += patch->size;
|
||||
index++;
|
||||
} else if (orig_byte != new_byte) {
|
||||
fprintf(stderr, PROGRAM_NAME ": Warning: Unpatched difference at offset: 0x%x\n", offset);
|
||||
fprintf(stderr, " Original ROM value: 0x%02x\n", orig_byte);
|
||||
fprintf(stderr, " Patched ROM value: 0x%02x\n", new_byte);
|
||||
fprintf(stderr, " Current patch offset: 0x%06x\n", patch->offset);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 7) {
|
||||
usage_exit(1);
|
||||
}
|
||||
|
||||
struct Symbol *symbols = NULL;
|
||||
parse_symbols(argv[1], &symbols);
|
||||
parse_symbols(argv[2], &symbols);
|
||||
|
||||
FILE *new_rom = xfopen(argv[3], 'r');
|
||||
FILE *orig_rom = xfopen(argv[4], 'r');
|
||||
struct Buffer *patches = process_template(argv[5], argv[6], new_rom, orig_rom, symbols);
|
||||
|
||||
if (!verify_completeness(orig_rom, new_rom, patches)) {
|
||||
fprintf(stderr, PROGRAM_NAME ": Warning: Not all ROM differences are defined by \"%s\"\n", argv[6]);
|
||||
}
|
||||
|
||||
symbol_free(symbols);
|
||||
fclose(new_rom);
|
||||
fclose(orig_rom);
|
||||
buffer_free(patches);
|
||||
return 0;
|
||||
}
|
40
vc/pokecrystal11.constants.asm
Normal file
40
vc/pokecrystal11.constants.asm
Normal file
@ -0,0 +1,40 @@
|
||||
INCLUDE "constants.asm"
|
||||
|
||||
; These are all the asm constants needed to make the crystal11_vc patch.
|
||||
|
||||
vc_const: MACRO
|
||||
println "00:{04x:\1} \1" ; same format as rgblink's .sym file
|
||||
ENDM
|
||||
|
||||
; [fight begin]
|
||||
vc_const SCREEN_HEIGHT_PX
|
||||
|
||||
; [print forbid 2]
|
||||
vc_const A_BUTTON
|
||||
; [print forbid 3]
|
||||
vc_const MAPGROUP_CIANWOOD
|
||||
vc_const MAP_CIANWOOD_PHOTO_STUDIO
|
||||
; [print forbid 5]
|
||||
vc_const NO_INPUT
|
||||
vc_const B_BUTTON
|
||||
vc_const D_UP
|
||||
vc_const D_DOWN
|
||||
|
||||
; [FPA 001 Begin]
|
||||
vc_const FISSURE
|
||||
; [FPA 002 Begin]
|
||||
vc_const SELFDESTRUCT
|
||||
; [FPA 003 Begin]
|
||||
vc_const THUNDER
|
||||
; [FPA 004 Begin]
|
||||
vc_const FLASH
|
||||
; [FPA 005 Begin]
|
||||
vc_const EXPLOSION
|
||||
; [FPA 006 Begin]
|
||||
vc_const HORN_DRILL
|
||||
; [FPA 007 Begin]
|
||||
vc_const HYPER_BEAM
|
||||
|
||||
; [FPA 042801 Begin]
|
||||
vc_const PRESENT
|
||||
vc_const anim_1gfx_command
|
698
vc/pokecrystal11.patch.template
Normal file
698
vc/pokecrystal11.patch.template
Normal file
@ -0,0 +1,698 @@
|
||||
;Format Sample
|
||||
;[xxxx] ;User-defined Name (Max:31 chars)
|
||||
;Mode = 1 ;1:Fixcode; 2:Fixvalue; 3:Mask; 4:Palette; 5:Double Frame Buffer
|
||||
;Type = 0 ;0:Begin 1:End
|
||||
;Index = 0 ;Index
|
||||
;Address = x1F8000 ;ROM Address
|
||||
;MemAddress = x2000 ;RAM Address
|
||||
;Fixcode = 0 ;Mode1: Fixed Rom Code; Mode2: Fixed Value
|
||||
;DelayFrame = 0 ;Delay Frame
|
||||
;FadeFrame = 0 ;Fade Frame 0:Off
|
||||
;DarkEnable0 = 0 ;0:Off, 1:On (for Normal Mode)
|
||||
;ReduceEnable0 = 0 ;0:Off, 1:On (for Normal Mode)
|
||||
;MotionBEnable0 = 0 ;0:Off, 1:Black Fade, 2:, 3:Frame Blend (for Normal Mode)
|
||||
;Dark0 = 10 ;0~10 (for Normal Mode)
|
||||
;ReduceColorR0 = 0 ;0~31 (for Normal Mode)
|
||||
;ReduceColorG0 = 0 ;0~31 (for Normal Mode)
|
||||
;ReduceColorB0 = 0 ;0~31 (for Normal Mode)
|
||||
;MotionBlur0 = 31 ;0~31 (for Normal Mode)
|
||||
;DarkEnable1 = 0 ;0:Off, 1:On (for Green Mode)
|
||||
;ReduceEnable1 = 0 ;0:Off, 1:On (for Green Mode)
|
||||
;MotionBEnable1 = 0 ;0:Off, 1:Black Fade, 2:, 3:Frame Blend (for Green Mode)
|
||||
;Dark1 = 10 ;0~10 (for Green Mode)
|
||||
;ReduceColorR1 = 0 ;0~31 (for Green Mode)
|
||||
;ReduceColorG1 = 0 ;0~31 (for Green Mode)
|
||||
;ReduceColorB1 = 0 ;0~31 (for Green Mode)
|
||||
;MotionBlur1 = 31 ;0~31 (for Green Mode)
|
||||
;PaletteX = c31,31,31 ;X:0~15, cR,G,B (0~31)
|
||||
|
||||
[Network10]
|
||||
Mode = 1
|
||||
Address = {HEX @+1 4}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[Network11]
|
||||
Mode = 1
|
||||
Address = {HEX @+1 4}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[send_send_buf2]
|
||||
Mode = 2
|
||||
Address = {HEX @ 4}
|
||||
Type = 29
|
||||
|
||||
[send_send_buf2_ret]
|
||||
Mode = 2
|
||||
Address = {HEX @ 4}
|
||||
Type = 30
|
||||
|
||||
[Network358]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 4
|
||||
|
||||
[Network359]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 4
|
||||
|
||||
[Network364]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
;fix pokemon ?? in name
|
||||
Type = 26
|
||||
|
||||
[Network360]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 4
|
||||
|
||||
[Network361]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 4
|
||||
|
||||
[Network362]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 4
|
||||
|
||||
[Network363]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 4
|
||||
|
||||
[Network_RECHECK]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 7
|
||||
|
||||
[send_byt2]
|
||||
Mode = 2
|
||||
Address = {HEX @+5}
|
||||
Type = 31
|
||||
|
||||
[send_byt2_ret]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 32
|
||||
|
||||
[send_byt2_wait]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[send_dummy]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 33
|
||||
|
||||
[send_dummy_wait]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[send_dummy_end]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 34
|
||||
|
||||
[NetworkDelay1]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[NetworkDelay2]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[NetworkDelay3]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[NetworkDelay4]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
[NetworkDelay6]
|
||||
Mode = 1
|
||||
Address = {HEX @+1}
|
||||
Fixcode = {PATCH +1}
|
||||
|
||||
;no use[Network_STOP]
|
||||
;Mode = 2
|
||||
;Address = 0xF4D34
|
||||
;Type = 8
|
||||
|
||||
;no use[Network_END]
|
||||
;Mode = 2
|
||||
;Address = 0xF4D3C
|
||||
;Type = 9
|
||||
|
||||
[Network_RESET]
|
||||
Mode = 2
|
||||
Address = {HEX @ 5}
|
||||
Type = 10
|
||||
|
||||
[E_YESNO]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 15
|
||||
|
||||
[linkCable fake begin]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 16
|
||||
|
||||
[linkCable fake end]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 17
|
||||
|
||||
;MURIYARI
|
||||
[linkCable block input]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 18
|
||||
[linkCable block input2]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 24
|
||||
[save game end]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 20
|
||||
[term_exit]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 25
|
||||
[room_check]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 27
|
||||
[to_play2_mons1]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 11
|
||||
[to_play2_trade]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 12
|
||||
[to_play2_battle]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 13
|
||||
[ret_heya]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 14
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;ROM:3FBCD ld b, $3E ; '>'
|
||||
;ROM:3FBCF inc de
|
||||
;ROM:3FBD0 call unk_2D55
|
||||
;ROM:3FBD3 xor a
|
||||
;ROM:3FBD4 ld [byte_FFD2], a
|
||||
;ROM:3FBD6 ld [byte_FF4A], a
|
||||
;ROM:3FBD8 call unk_31C2
|
||||
;ROM:3FBDB call unk_2FE2
|
||||
;
|
||||
;ROM:3FBCD: 06 3E 13 CD
|
||||
|
||||
;0003fbb5h: 06 3E 13 CD ; .>.?
|
||||
|
||||
[fight begin]
|
||||
Mode = 11
|
||||
Type = 0
|
||||
Index = 1
|
||||
Address = {HEx @}
|
||||
Fixcode={db SCREEN_HEIGHT_PX}
|
||||
|
||||
;12 1b 0b 79 b0 find next C9
|
||||
[BiographySave_ret]
|
||||
Mode = 2
|
||||
Address = {HEX @}
|
||||
Type = 60
|
||||
|
||||
|
||||
; print forbid 1
|
||||
;ROM:1758D ld a, [byte_FFA9]
|
||||
;ROM:1758F and 2
|
||||
;ROM:17591 jr nz, unk_75B4
|
||||
;ROM:17593 ld a, [byte_FFA9]
|
||||
;ROM:17595 and 1 ;e6 01
|
||||
;ROM:17597 jr nz, unk_75A1
|
||||
;
|
||||
; change "and 1" to "and 0"
|
||||
;00017595h: E6 01 20 08 CD BF 75 CD 2E 03 18 E9 FA 57 CE F5 ; ? .涂u?..辁W熙
|
||||
;00016c76h: E6 01 20 08 CD A0 6C CD 5A 04 18 E9 FA 63 CF F5 ; ? .蜖l蚙..辁c硝
|
||||
[print forbid 1]
|
||||
Mode = 1
|
||||
Address = {hex @}
|
||||
Fixcode={patch}
|
||||
|
||||
|
||||
|
||||
[print forbid 2]
|
||||
Mode = 6
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
MemAddress={hex hJoyPressed}
|
||||
Fixcode={db NO_INPUT}
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wWindowStackPointer wWindowStackPointer+1 wMenuJoypad wMenuSelection wMenuSelection wMenuCursorY hJoyPressed hJoyPressed hJoyPressed hJoyPressed}
|
||||
ConditionValueB = {dws_ == == == >= <= == != != != != }
|
||||
ConditionValueC = {dws_ 0xdd 0xd3 A_BUTTON 0x00 0x0f 0x03 D_DOWN D_UP B_BUTTON NO_INPUT }
|
||||
|
||||
; -----ddddfffffff99999ccccc77777----0xd9c7 no ..............Mem Write: pc32 = 0x230b addr = 0xd9c7 value = 0x8
|
||||
; 0xd9c7 is the room number.
|
||||
|
||||
|
||||
[print forbid 3]
|
||||
Mode = 6
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
MemAddress={hex hJoyPressed}
|
||||
Fixcode={db NO_INPUT}
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wWindowStackPointer wWindowStackPointer+1 wMenuJoypad wMenuSelection wMenuCursorY wMapGroup wMapNumber wYCoord wXCoord hJoyPressed hJoyPressed hJoyPressed hJoyPressed}
|
||||
ConditionValueB = {dws_ == == == == == == == == == != != != != }
|
||||
ConditionValueC = {dws_ 0xaf 0xdf NO_INPUT 0x00 0x01 MAPGROUP_CIANWOOD MAP_CIANWOOD_PHOTO_STUDIO 0x04 0x02 D_DOWN D_UP B_BUTTON NO_INPUT }
|
||||
|
||||
|
||||
;ROM:BB29C call unk_934
|
||||
;ROM:BB29F ld a, [byte_FFA9]
|
||||
;ROM:BB2A1 and $B
|
||||
;ROM:BB2A3 jr z, unk_B29C
|
||||
;ROM:BB2A5 and 8
|
||||
;ROM:BB2A7 jr nz, unk_B2AA
|
||||
;ROM:BB2A9 ret
|
||||
; 000bb2a5h: E6 08 20 01
|
||||
; 000b92a3h: E6 08 20 01 ; ? .
|
||||
; change "and 8" to "and 0"
|
||||
[print forbid 4]
|
||||
Mode = 1
|
||||
Address = {hex @}
|
||||
Fixcode={patch}
|
||||
|
||||
|
||||
;ROM:401D6 call unk_50A5
|
||||
;ROM:401D9 ld hl, $FFA9
|
||||
;ROM:401DC ld a, [hl]
|
||||
;ROM:401DD and 2
|
||||
;ROM:401DF jr nz, unk_1F8
|
||||
;ROM:401E1 ld a, [hl]
|
||||
;ROM:401E2 and 1
|
||||
;ROM:401E4 jr nz, unk_1EE
|
||||
;ROM:401E6 call unk_4562
|
||||
;ROM:401E9 ret nc
|
||||
;ROM:401EA call unk_4114
|
||||
;ROM:401ED ret
|
||||
; -----6666666666ddddddddd88888----0xc6d8 no ..............Mem Write: pc32 = 0x4109b addr = 0xc6d8 value = 0x0
|
||||
|
||||
;00040266h: 7E E6 01 20 08 ; ~? .
|
||||
[print forbid 5]
|
||||
Mode = 6
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
MemAddress={hex hJoyPressed}
|
||||
Fixcode={db NO_INPUT}
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wWindowStackPointer wWindowStackPointer+1 wMenuJoypad wMenuSelection wDexArrowCursorPosIndex hJoyPressed hJoyPressed hJoyPressed hJoyPressed}
|
||||
ConditionValueB = {dws_ == == == == == != != != != }
|
||||
ConditionValueC = {dws_ 0xa1 0xdb A_BUTTON 0x00 0x03 D_DOWN D_UP B_BUTTON NO_INPUT }
|
||||
|
||||
|
||||
|
||||
|
||||
;0x29e97
|
||||
; call ir_main
|
||||
; ld d,a ; IR_STAT
|
||||
; xor a
|
||||
|
||||
|
||||
; _IRcomm_end 0x2a1b9
|
||||
; ld hl,ir_read_buf | 21 50 c7
|
||||
; ld de,ir_read_buf_stk | 11 00 c8
|
||||
; ld bc,15 |
|
||||
; call block_move |
|
||||
; |
|
||||
;00104bf8h: FE 03 30 24
|
||||
;00104bf0h: FE 03 30 24 3E 41 21 0B 51 CF CD FB 50 ; ?0$>A!.Q贤鸓
|
||||
;00104bf0h: FE 03 30 24 3E 41 21 0B 51 CF CD FB 50 ; ?0$>A!.Q贤鸓
|
||||
;the code below is Set_send_data2
|
||||
; 3E 41 21 0A 51 CF CD FA 50
|
||||
; 3E 41 21 0B 51 CF CD FB 50
|
||||
; ------->
|
||||
; BCALL G_BANK0b,set_send_data2
|
||||
; call read_buf_clr
|
||||
;
|
||||
|
||||
;001048dbh: 3E 02 EA 01 CA 3E 14 EA 02 CA F0 FF F5 CD 94 4A
|
||||
;001048dbh: 3E 02 EA 01 CA 3E 14 EA 02 CA F0 FF F5 CD 9D 4A
|
||||
[infrared fake 0]
|
||||
Mode = 1
|
||||
Address = {hex @}
|
||||
Fixcode={PATCH}
|
||||
|
||||
|
||||
;00104c3ch: CD 66 4D CD 9E 4D CD E5 4D F0 BC FE 10 CA 24 4D
|
||||
;00104a95h: F3 3E 3A 21 E9 4F CF CD 5E 4D CD 96 4D CD DD 4D ; ?:!镺贤^M蜄M洼M
|
||||
;00104a9ch: CD 5E 4D CD 96 4D CD DD 4D F0 BC FE 10 ; 蚟M蜄M洼M鸺?
|
||||
|
||||
[infrared fake 1]
|
||||
Mode = 1
|
||||
Address = {hex @}
|
||||
Fixcode={patch}
|
||||
|
||||
[infrared fake 2]
|
||||
Mode = 2
|
||||
Address = {hex @}
|
||||
Type = 101
|
||||
|
||||
[infrared fake 3]
|
||||
Mode = 2
|
||||
Address = {hex @}
|
||||
Type = 102
|
||||
|
||||
[infrared fake 4]
|
||||
Mode = 2
|
||||
Address = {hex @}
|
||||
Type = 103
|
||||
|
||||
|
||||
;/////////////
|
||||
;////fpa////////
|
||||
;/////////rangel zhang ///////////
|
||||
|
||||
;PC:51-4118=20 000CC118 LY:012 AF:00A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFC1
|
||||
;PC:51-411A=FA 000CC11A LY:012 AF:00A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFC1
|
||||
;PC:51-411D=CB 000CC11D LY:012 AF:61A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFC1
|
||||
;PC:51-411F=20 000CC11F LY:012 AF:61A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFC1
|
||||
;PC:51-4121=CD 000CC121 LY:012 AF:61A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFC1
|
||||
;PC:51-417A=CD 000CC17A LY:012 AF:61A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFBF
|
||||
;PC:51-41CA=3E 000CC1CA LY:012 AF:61A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFBD
|
||||
;PC:51-41CC=EA 000CC1CC LY:012 AF:01A0 BC:E400 DE:E4E4 HL:FFA0 SP:DFBD
|
||||
|
||||
;ROM:CC118 jr nz, unk_C14D
|
||||
;ROM:CC11A ld a, [byte_D1AB]
|
||||
;ROM:CC11D bit 7, a
|
||||
;ROM:CC11F jr nz, unk_C138
|
||||
;ROM:CC121 call unk_417A
|
||||
;ROM:CC124 call unk_415A
|
||||
;ROM:CC127 call unk_47F7
|
||||
|
||||
;000cc13eh: 6F 26 00 11 ; o&..
|
||||
;000cc156h: 6F 26 00 11 ; o&..
|
||||
;000cc137h: 38 17 CD 92 41 CD 72 41 CD 95 48 CD D3 41 AF E0 ; 8.蛼A蛂A蜁H陀A
|
||||
;000cc128h: 38 17 CD A1 41 CD 63 41 CD A4 48 CD E2 41 AF E0 ; 8.汀A蚦A亭H外A
|
||||
|
||||
;the 7th bit of the [byte_D1AB],decide whether the animation should be played.
|
||||
;if it's zero , the game code will play fighting animation . otherwise, game code
|
||||
; will jump to unk_C138 and avoiding playing animation.
|
||||
; so we can begin out FPA patch right at address 0xcc121 .
|
||||
|
||||
|
||||
;DarkEnable0 = 0 ;0:Off, 1:On (for Normal Mode)
|
||||
;ReduceEnable0 = 0 ;0:Off, 1:On (for Normal Mode)
|
||||
;MotionBEnable0 = 0 ;0:Off, 1:Black Fade, 2:, 3:Frame Blend (for Normal Mode)
|
||||
;Dark0 = 10 ;0~10 (for Normal Mode)
|
||||
;012532
|
||||
;
|
||||
[FPA 001 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 4
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 11
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID}
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ FISSURE }
|
||||
|
||||
;ROM:35D09 ld [byte_CFB6], a
|
||||
;ROM:35D0C ld a, d
|
||||
;ROM:35D0D ld [byte_CFB7], a
|
||||
;ROM:35D10 ld c, 3
|
||||
;ROM:35D12 call unk_468
|
||||
;ROM:35D15 ld hl, $40E5
|
||||
;ROM:35D18 ld a, $33 ; '3'
|
||||
;ROM:35D1A rst 8
|
||||
;ROM:35D1B ret
|
||||
; EA B6 CF 7A EA B7 CF 0E 03 CD 68 04 21 E5 40 3E
|
||||
;00035d09h: EA C2 CF 7A EA C3 CF 0E 03 CD 68 04 21 D6 40 3E
|
||||
;00035d09h: EA C2 CF 7A EA C3 CF 0E 03 CD 68 04 21 D8 40 3E
|
||||
|
||||
;******dc7d--------------- Mem Write: pc32 = 0x30a7 addr = 0xd066 value = 0x2c
|
||||
;******dc7d--------------- Mem Write: pc32 = 0x30a7 addr = 0xd067 value = 0x3a
|
||||
;******dc7d--------------- Mem Write: pc32 = 0x30a7 addr = 0xd068 value = 0xb8
|
||||
;******dc7d--------------- Mem Write: pc32 = 0x30a7 addr = 0xd069 value = 0x50
|
||||
; ------------ Mem Write: pc32 = 0x35d09 addr = 0xcfb6 value = 0x78
|
||||
;s e l d e s c
|
||||
;
|
||||
|
||||
[FPA 002 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 4
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 11
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID }
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ SELFDESTRUCT}
|
||||
|
||||
|
||||
; lightening
|
||||
; -------------- Mem Write: pc32 = 0x35d09 addr = 0xcfb6 value = 0x57
|
||||
[FPA 003 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 4
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 15
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID}
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ THUNDER }
|
||||
|
||||
|
||||
|
||||
|
||||
;ji wa lei 011800
|
||||
|
||||
[FPA 004 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 4
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 15
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID}
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ FLASH }
|
||||
|
||||
|
||||
;skill name 1 : ..............Mem Write: pc32 = 0x30db addr = 0xcf87 value = 0x2c
|
||||
;skill name 2 : ..............Mem Write: pc32 = 0x30db addr = 0xcf88 value = 0x3a
|
||||
;skill name 3 : ..............Mem Write: pc32 = 0x30db addr = 0xcf89 value = 0xb8
|
||||
;skill name 4 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8a value = 0x50
|
||||
;skill name 5 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8b value = 0x8f
|
||||
;skill name 6 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8c value = 0x9d
|
||||
; include 2 pieces of animationl.
|
||||
;ji ba lu 011607
|
||||
|
||||
[FPA 005 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 4
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 15
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID}
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ EXPLOSION}
|
||||
|
||||
|
||||
;skill name 1 : ..............Mem Write: pc32 = 0x30db addr = 0xcf87 value = 0x30
|
||||
;skill name 2 : ..............Mem Write: pc32 = 0x30db addr = 0xcf88 value = 0xb2
|
||||
;skill name 3 : ..............Mem Write: pc32 = 0x30db addr = 0xcf89 value = 0x3a
|
||||
;skill name 4 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8a value = 0xb8
|
||||
;skill name 5 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8b value = 0xca
|
||||
;skill name 6 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8c value = 0xc2
|
||||
; da yi ba ha ku ci 011441
|
||||
|
||||
[FPA 006 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 4
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 11
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID }
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ HORN_DRILL}
|
||||
|
||||
|
||||
|
||||
;skill name 1 : ..............Mem Write: pc32 = 0x30db addr = 0xcf87 value = 0x9b
|
||||
;skill name 2 : ..............Mem Write: pc32 = 0x30db addr = 0xcf88 value = 0xa5
|
||||
;skill name 3 : ..............Mem Write: pc32 = 0x30db addr = 0xcf89 value = 0xac
|
||||
;skill name 4 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8a value = 0x8b
|
||||
;skill name 5 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8b value = 0xae
|
||||
;skill name 6 : ..............Mem Write: pc32 = 0x30db addr = 0xcf8c value = 0x50
|
||||
; 011251
|
||||
;
|
||||
[FPA 007 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 5
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 7
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID }
|
||||
ConditionValueB = {dws_ == }
|
||||
ConditionValueC = {dws_ HYPER_BEAM}
|
||||
|
||||
|
||||
|
||||
|
||||
;-----111111111111111144444444444444----0xc902 no ..............Mem Write: pc32 = 0xcc46a addr = 0xc902 value = 0xd
|
||||
|
||||
;000cc473h: FE 4F D0 cd ; 﨩?
|
||||
;000cc495h: FE 4F D0 CD ; 﨩型
|
||||
;000cc497h: FE 4F D0 CD ; 﨩型
|
||||
; -------------0xd4170xd4170xd4170xd417--------------- Mem Write: pc32 = 0x3a89 addr = 0xd417 value = 0xd1
|
||||
;000cc486h: FE 4F D0 CD 7D 3A 22 FA 19 D4 22 C5 E5 6F 26 00 ; 﨩型}:"??佩o&.
|
||||
[FPA 042801 Begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {HEX @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 5
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 11
|
||||
ConditionType = 0
|
||||
ConditionValueA = {dws_ wFXAnimID wBattleAnimByte }
|
||||
ConditionValueB = {dws_ == == }
|
||||
ConditionValueC = {dws_ PRESENT anim_1gfx_command}
|
||||
|
||||
|
||||
|
||||
|
||||
;ROM:CC139 call unk_4192
|
||||
;ROM:CC13C call unk_4172
|
||||
;ROM:CC13F call unk_4895
|
||||
;ROM:CC142 call unk_41D3
|
||||
;ROM:CC145 xor a
|
||||
|
||||
;ROM:CC154 jr z, unk_C16E
|
||||
;ROM:CC156 ld l, a
|
||||
;ROM:CC157 ld h, 0
|
||||
;ROM:CC159 ld de, $10E
|
||||
;ROM:CC15C add hl, de
|
||||
;ROM:CC15D ld a, l
|
||||
; CC156 6F 26 00 11 0E 01
|
||||
|
||||
; 000cc147h: 6F 26 00 11 0E 01 ; o&....
|
||||
|
||||
;exit point
|
||||
|
||||
[FPA 001 End]
|
||||
Mode = 3
|
||||
Type = 1
|
||||
Address = {hex @}
|
||||
|
||||
|
||||
;-----ddddff0xff690xff69fffff----0xffa0 no ....-------------..........Mem Write: pc32 = 0x8c352 addr = 0xffa0 value = 0x1
|
||||
;-----ddddff0xff690xff69fffff----0xce57 no ....----5555555577777---------..........Mem Write: pc32 = 0x8c483 addr = 0xce57 value = 0x1a
|
||||
;0008c352h: 36 01 FA 57 CE CB 7F 20 08 ; 6.鶺嗡 .
|
||||
;0008c229h: 36 01 FA 57 CF CB 7F 20 08 CD 14 43 CD 5A 04 18 ; 6.鶺纤 .?C蚙..
|
||||
[FPA link fight begin]
|
||||
Mode = 3
|
||||
Type = 0
|
||||
Address = {hex @}
|
||||
DarkEnable0 = 1
|
||||
Dark0 = 5
|
||||
MotionBEnable0 = 3
|
||||
MotionBlur0 = 11
|
||||
|
||||
;-----ddddff0xff690xff69fffff----0xffa0 no ....-------------..........Mem Write: pc32 = 0x8c382 addr = 0xffa0 value = 0x0
|
||||
;0008c382h: E0 A0 CD 2E 03 C9 ; 酄?.?
|
||||
;******ccccccccccceeeeeeeeeee55555555577777777--------------- Mem Write: pc32 = 0x8c483 addr = 0xce57 value = 0x15
|
||||
;******ccccccccccceeeeeeeeeee55555555577777777--------------- Mem Write: pc32 = 0x8c483 addr = 0xce57 value = 0x16
|
||||
;******ccccccccccceeeeeeeeeee55555555577777777--------------- Mem Write: pc32 = 0x8c483 addr = 0xce57 value = 0x17
|
||||
|
||||
;40 90 e4 01 3E at 3E
|
||||
;0008c3e4h: 40 90 E4 01 3E at 3E ; @愪.>
|
||||
[FPA link fight End0]
|
||||
Mode = 3
|
||||
Type = 1
|
||||
Address = {HEx @}
|
||||
|
||||
;3D 20 EF C9 3E 01 at 3E
|
||||
; 0008c439h: 3D 20 EF C9 3E at 3e ; = 锷>
|
||||
[FPA link fight End1]
|
||||
Mode = 3
|
||||
Type = 1
|
||||
Address = {HEx @}
|
||||
|
||||
;01 FF 3E 01 at 3E
|
||||
;0008c576h: 01 FF 3E 01 ; .>.
|
||||
[FPA link fight End2]
|
||||
Mode = 3
|
||||
Type = 1
|
||||
Address = {HEx @}
|
||||
|
||||
;32 00 19 00 3e 01 at 3e
|
||||
;0008c764h: 32 00 19 00 3E 01 ; 2...>.
|
||||
[FPA link fight End3]
|
||||
Mode = 3
|
||||
Type = 1
|
||||
Address = {HEx @}
|
||||
|
||||
;ROM:8C25A ld [byte_FFC6], a
|
||||
;ROM:8C25C ld [byte_FFC7], a
|
||||
;ROM:8C25E ld [byte_FFC8], a
|
||||
;ROM:8C260 ld [byte_FFD0], a
|
||||
;ROM:8C262 ld a, 1
|
||||
;ROM:8C264 ld [byte_FF70], a
|
||||
;ROM:8C266 pop af
|
||||
;ROM:8C267 ld [byte_FF9E], a --------------------at here .
|
||||
;ROM:8C269 call unk_45A
|
||||
;ROM:8C26C ret
|
||||
|
||||
|
||||
;ROM:8C298 xor a searching code : AF 22 22 77 CD
|
||||
;ROM:8C299 ldi [hl], a
|
||||
;ROM:8C29A ldi [hl], a
|
||||
;ROM:8C29B ld [hl], a
|
||||
;ROM:8C29C call unk_46D8
|
||||
;ROM:8C29F ret
|
||||
;0008c298h: AF 22 22 77 CD ; ?"w?
|
||||
|
||||
|
||||
[FPA link fight End4]
|
||||
Mode = 3
|
||||
Type = 1
|
||||
Address = {hex @}
|
Loading…
Reference in New Issue
Block a user