Skip to content

Instantly share code, notes, and snippets.

@RobertTheSable
Last active April 20, 2022 02:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RobertTheSable/6d838827998d195972ca03f02bcfbda1 to your computer and use it in GitHub Desktop.
Save RobertTheSable/6d838827998d195972ca03f02bcfbda1 to your computer and use it in GitHub Desktop.
Asar patch to make the sea dragon class work in FE3
lorom
; patch to make the sea dragon class work in FE3
; has not been extensivley tested
; so, caveat emptor
; the effect of this patch is:
; - using the unobtainable dark dragon stone turns Tiki into a Sea Dragon instead of a Dark Dragon.
; - the Sea Dragon's battle sprite is switched from Fire Dragon > Ice Dragon,
; because I think it matches the map sprite better.
; compatibility stuff
check title "SHVC FIREEMBLEM "
if read1($00FFDB) == $01
!targetingHook1 = $83A409
!targetingHook2 = $83E178
!targetingHook3 = $83F91B
!breathHook = $83B061
elseif read1($00FFDB) == $00
!targetingHook1 = $83A3F4
!targetingHook2 = $83E175
!targetingHook3 = $83f918
!breathHook = $83B04C
else
error "Unknown revision"
endif
; hooks
; 1st after picking "attack"
ORG $81BE38
JSL targetingBreathCheck
; 2nd after picking "attack"
ORG $81BE4C
JSL targetingBreathCheck
; 3rd after picking "attack"
ORG $81CED5
JSL targetingBreathCheck
ORG !targetingHook1
JSL targetingBreathCheck
; makes attack option appear?
ORG !targetingHook2
JSL targetingBreathCheck
ORG !targetingHook3
JSL targetingBreathCheck
ORG !breathHook
JSL battleBreathCheck
rts
; ORG $83849F
; original dragon data table
; dragonClassTable:
; db $10, $26, $28, $29, $27, $2B, $2C
; dragonStoneTable:
; db $4F, $51, $52, $53, $54, $55, $56
; dragonBreathTable:
; db $29, $2A, $29, $2B, $2B, $2C, $29
ORG $93D2C4
getBreathType:
php
sep #$30
ldx.b #$00
.loop:
cmp dragonClassTable,X
beq .endLoop
inx
cpx.b #$09 ; increased the count here after expanding the table
bne .loop
.hang:
; loops forever?
bra .hang
.endLoop:
lda dragonBreathTable,X
cmp.b #$2C
bne .exit
lda $07DF
; change divine dragon breath based on what book we're in
cmp.b #$15
bcs .inBook2
lda.b #$2A
bra .exit
.inBook2:
lda.b #$2C
.exit:
plp
rtl
ORG $93D305
loadDragonClassFromStone:
php
sep #$30
ldx #$00
-:
cmp.l dragonStoneTable,X
beq +
inx
cpx #$08 ; did not increase the count because I didn't add a "seastone"
bne -
-:
bra - ; infinite loop?
+:
lda.l dragonClassTable,X
plp
rtl
; animation swaps:
ORG $958928
; the animation tileset
dw $EFC6
ORG $958853
; the palette
dw $D9F1
ORG $958DC1
; the animation "script"
dw $9033
; repoint this to wherever
ORG $FFB930
; replaces $83FEED
targetingBreathCheck:
php
sep #$30
lda ActiveUnit.ClassId
cmp.b #$10
beq .currentClassIsADragon
cmp.b #$27
beq .currentClassIsADragon
cmp.b #$26
beq .currentClassIsADragon
cmp.b #$2C
beq .currentClassIsADragon
cmp.b #$29
beq .currentClassIsADragon
cmp.b #$2b
bne .exit
.currentClassIsADragon:
; if the current attacker's class is a dargon,
; then clear out their weapon inventory
; and replace the first item with the correct breath type
ldx.b #$00
.loop:
lda.b #$FF
sta ActiveUnit.Inventory.Weapons,x
inx
cpx.b #$08
bne .loop
lda ActiveUnit.ClassId
jsl getBreathType
sta ActiveUnit.Inventory.Weapons
.exit:
plp
rtl
skip 6
; ORG $FFB970
; sets the active weapon to the correct breath type
battleBreathCheck:
cmp.b #$10
beq .isADragon
cmp.b #$2C
beq .isADragon
cmp.b #$29
beq .isADragon
cmp.b #$26
beq .isADragon
cmp.b #$28
beq .isADragon
cmp.b #$2B
beq .isADragon
cmp.b #$27
bne .isNotADragon
.isADragon:
jsl getBreathType
sta $075F,Y
lda.b #$FF
sta $0777,Y
bra .exit
.isNotADragon:
lda.b #$FF
sta $075F,Y
sta $0777,Y
.exit:
rep #$20
rtl
dragonClassTable:
db $10, $26, $28, $29, $27, $2B, $2C, $2A
dragonStoneTable:
db $4F, $51, $52, $53, $54, $55, $56
dragonBreathTable:
db $29, $2A, $29, $2B, $29, $2C, $29, $2B
; structs to make load/store instructions more understandable
struct ActiveUnit $7F4400 ; note: offsets are in hexadecimal
.UnitID: skip 1 ; offset 0
.ClassId: skip 1 ; offset 1
.Level: skip 1 ; offset 2
.HP: skip 1 ; offset 3
.MaxHP: skip 1 ; offset 4
.EXP: skip 1 ; offset 5
.Terrain: skip 2 ; offset 6, 2 bytes
; Makes unit unselectable if hidden
.Movement: skip 1 ; offset 8
.Strength: skip 1 ; offset 9
.Skill: skip 1 ; offset A
.Speed: skip 1 ; offset B
.Defense: skip 1 ; offset C
.Resistance: skip 1 ; offset D
.Luck: skip 1 ; offset E
.WeaponLevel: skip 1 ; offset F
.XPosition: skip 1 ; offset 10
.YPosition: skip 1 ; offset 11
.HasMoved ; offset 12
.IsDead: skip 1 ; may also indicate if a unit is dead
.ResBoostTimer: skip 1 ; offset 13
.MountedClassID: skip 1 ; offset 14
.UnitWasSelected ; offset 15 is used both to indicate selection on the prep screen
.TransformTimer: skip 1 ; and the countdown timer for transformed characters
.NameID: skip 1 ; offset 16
.PortraitID: skip 1 ; offset 17
.AI1: skip 2 ; offset 18, 2 bytes
.AI2: skip 2 ; 1A, 2 bytes
.AI3: skip 2 ; 1C, 2 bytes
.Money: skip 2 ; 1E, 2 bytes
endstruct
struct Inventory extends ActiveUnit
.Weapons:
.Weapon1: skip 1
.Weapon2: skip 1
.Weapon3: skip 1
.Weapon4: skip 1
.Weapon1Uses: skip 1
.Weapon2Uses: skip 1
.Weapon3Uses: skip 1
.Weapon4Uses: skip 1
.Items:
.Item1: skip 1
.Item2: skip 1
.Item3: skip 1
.Item4: skip 1
.Item1Uses: skip 1
.Item2Uses: skip 1
.Item3Uses: skip 1
.Item4Uses: skip 1
endstruct
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment