Code repository for 2.0

36 posts in this topic

New status text code:


org $c14587
;At end of routine: bit 0 = Regen, Bit 1 = Rerise, Bit 2 = Sap
    lda $2ebe,x                                ; status effect 2
    lsr #3                                    ; shift to bit 3
    ora $2ebf,x                                ; status effect 3
    ora $2ec0,x                                ; status effect 4
    lsr                                        ; index
    and #$07                                ; filter out unneeded bits

padbyte $FF : pad $c145b3

; $20-$23 = Regen
; $24-$25 = Sap
; $20, $26-$28 = Rerise
org $c2ade1
    db $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF    ; nothing
    db $20,$21,$22,$23,$FF,$FF,$FF,$FF,$FF,$FF  ; Regen
    db $20,$26,$27,$28,$FF,$FF,$FF,$FF,$FF,$FF    ; Rerise
    db $20,$21,$22,$23,$20,$26,$27,$28,$FF,$FF    ; Regen, Rerise
    db $24,$25,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF    ; Sap
    db $82,$87,$84,$80,$93,$84,$91,$FF,$FF,$FF    ; Sap, Regen
    db $24,$25,$FF,$20,$26,$27,$28,$FF,$FF,$FF    ; Sap, Rerise
    db $82,$87,$84,$80,$93,$84,$91,$FF,$FF,$FF    ; Sap, Rerise, Regen

org $c481c0
    db $F0,$E0,$F8,$90,$DB,$93,$FF,$E4,$F7,$A7,$FF,$94,$DF,$93,$DB,$00
    db $00,$00,$00,$00,$9C,$18,$FF,$A5,$F7,$25,$BF,$1D,$DF,$84,$DE,$18
    db $00,$00,$00,$00,$EF,$CA,$FF,$2D,$FF,$C9,$ED,$09,$FD,$E9,$FD,$00
    db $00,$00,$00,$00,$00,$00,$80,$00,$80,$00,$80,$00,$80,$00,$80,$00
    db $70,$70,$F0,$80,$C3,$83,$F7,$64,$7E,$14,$1E,$14,$FF,$E3,$F3,$00
    db $00,$00,$00,$00,$9E,$1C,$DF,$92,$DB,$92,$DF,$9C,$FE,$50,$78,$10
    db $00,$00,$03,$02,$BF,$28,$FF,$B2,$FB,$22,$33,$22,$F3,$A2,$F3,$00
    db $00,$00,$00,$00,$7B,$73,$FF,$84,$77,$67,$7F,$14,$FF,$E3,$F3,$00
    db $00,$00,$00,$00,$80,$00,$C0,$80,$C0,$00,$00,$00,$C0,$80,$C0,$00
    db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00

Share this post

Link to post
Share on other sites

Made of Explodium - DONE

EDIT: Updated to fix a bug. No changed requirements (just changed the CPX to a CPY).


	; Add a multiplier for Exploder when used by a player character
; 1 Spell Power = +50% damage
; Updated to fix a bug where Exploder cast by characters wouldn't gain the multiplier from Spell Power.
!freespace = $C2A8D2    ; 12 bytes
	; Exploder effect
org $C23FFC
JSR newfunc
	org !freespace
      TDC         ; Clear 16-bit A
      CPY #$08    ; Check if monster
      BCS .exit   ; If monster, multiplier = 0
      LDA $11A6   ; Else, use Spell Power as multiplier
.exit STA $BC     ; Store multiplier


Edited by seibaby

Share this post

Link to post
Share on other sites

Status display bugfix

org $C14587
LDA $2EBE,X   ; Status byte 2 (for Sap)
ROL #2        ; Rotate Sap into carry
TDC           ; Clear A
ROL           ; Rotate Sap into bit 0
XBA           ; Save Sap
	LDA $2EC0,X   ; Status byte 4 (Rerise byte)
LSR #3        ; Shift Rerise into carry
XBA           ; Get Sap again
ROL           ; Rotate Rerise into bit 0, Sap into bit 1
XBA           ; Save Sap and Rerise
	LDA $2EBF,X   ; Status byte (for Regen)
LSR #2        ; Shift Regen into carry
XBA           ; Get Sap and Rerise
ROL           ; Rotate Regen into bit 0, Rerise into bit 1, Sap into bit 2

Share this post

Link to post
Share on other sites

Updated stop code, replaces the original entirely:


org $c2265b
jsr $3c04 ; old rippler space
org $c23c04
pha            ; save A
lda $3330,x
and #$EF
sta $3330,x
ora #$80

Edited by darknil

Share this post

Link to post
Share on other sites

I mentioned a potential source of the "Sleep rage attack missing large sprite enemies" bug in the Coming Soon: 2.0 thread. While the bug itself has not been confirmed in 2.0 beta, I wanted to post a potential fix, in case the need arises. I'm pretty green, so I would greatly appreciate if someone with more experience could look this over. I don't know (yet) how to actually make patches, and I'm not familiar with any asm compilers, so I'm just posting the hex below.

This fix does not require any additional bytes.


Special Attack Status Immunity (1.9 code)

00C2:6760 48           pha           ; A = updated status byte (1-4)
00C2:6761 89 80        bit #80       ; Death, Sleep, Reflect, or Float
00C2:6763 F0 05        beq 676A      ; branch if highest bit not set  // BUG
00C2:6765 A9 02        lda #02
00C2:6767 0C A2 11     tsb 11A2      ; set "miss if protected against death" flag
00C2:676A 68           pla           ; A = updated status byte
00C2:676B 20 E5 61     jsr 61E5
00C2:676E 60           rts

00C2:61E5 9D AA 11     sta 11AA,x    ; store updated status byte
00C2:61E8 A9 10        lda #10
00C2:61EA 0C A4 11     tsb 11A4      ; use stamina in evasion formula
00C2:61ED 60           rts

Proposed patch

 --> 6760 9D AA 11     sta 11AA,x    ; store updated status byte
 --> 6763 10 03        bpl 6768      ; if possible death bit not set, branch
 --> 6765 20 E5 61     jsr 61E5      ; else, set death miss flag
 --> 6768 A9 10        lda #10
 --> 676A 0C A4 11     tsb 11A4      ; use stamina in evasion formula
 --> 676D 60           rts
 --> 676E EA           nop

 --> 61E5 8A           txa           ; A = status byte index
 --> 61E6 D0 05        bne 61ED      ; death status is on status byte 0
 --> 61E8 A9 02        lda #02
 --> 61EA 0C A2 11     tsb 11A2      ; set "miss if protected against death" flag
 --> 61ED 60           rts


Edited by Bropedio

Share this post

Link to post
Share on other sites

Tank & Spank 1.1beta

There was an issue in Tank & Spank where Love Token would be prevented by Blind/Berserk/Image just like Cover is. This should fix it.
NOTE: the free space requirements have changed and the freespace defines needs to be set up again. The main part of the code now requires 114 damn bytes. I set the define for it it to the newly freed up chunk where the Rage table used to be, for testing.


;Tank & Spank (previously Cover Knight and Smart Cover)
;by Seibaby
;v1.01 - Fixed a bug with Love Token being prevented by Image, Dark, and Berserk
;v1.0 - Only allows back row targets for Stamina-based cover
;       Disables Cover when Dancing
;v0.9 - Disables Interceptor and halves Evasion when Covering
;v0.7 - Fixes a bug where Knight wouldn't reset Defending stance when Covering
;v0.6 - New Smart Cover logic
;       Some Cover nerfs
;v0.5 - Fixes an issue with Knights not taking targets' statuses into
;       account (Image and Clear, but also Zombie and Petrify)
;v0.4 - Fixes a bug causing Knights to Cover monsters attacking other
;       monsters
;v0.3 - Adds an exception to not trigger Cover if the Knight is Near Fatal
;       and the target is healthy.
;v0.2 - Fixes a bug that caused the wrong statuses (on the target) to be
;       considered for whether or not to disable True Knight.
    ;Changes the True Knight effect to trigger with a Stamina / 192 chance even if
;the target isn't in Near Fatal status.
    ;New Smart Cover patch, which disables True Knight for all attacks
;originating from a player character, unless that character is uncontrollable,
;in which case it will only disable it if the attack comes from a healing weapon,
;or if the weapon is elemental and the target absorbs/nullifies that element.
;It also considers a few extra statuses for purposes of disabling True Knight.
;ON TARGET: Death, Petrify, Zombie, Magitek, and Image
;           (in addition to Clear)
;ON KNIGHT: Dark, Magitek, Image, Berserk
;           (in addition to Death, Petrify, Clear, Zombie, Sleep, and Muddled)
;xkas 0.06
!smartCover = $C2FAD0       ;Requires 114 bytes of free space
!halveEvade = ;Requires 20 bytes of free space
!noDogBlock = ;Requires 9 bytes of free space
    ;A few notes on the changes made to these functions:
;Entering this function, A is 16-bit and X/Y are 8-bit. Register width is
;never changed and the call following this function doesn't care about Carry,
;so I have removed a bunch of useless PHP/PLP and REP #$20 throughout, to make
;room for the new code.
;I have also removed some code related to monsters using True Knight, which was
;supported in vanilla, but unused (and remains so in BNW). The check for if the
;bodyguard was Controlled was also removed (doubly useless).
    org $C2123A
    ;True Knight and Love Token
org $C2123B
        LDA $B2
        BIT #$0002          ;Is "No critical and Ignore True Knight" set?
        BNE .exit           ;Exit if so
        LDA $B8             ;intended target(s).  to my knowledge, there's only
                            ;one intended target set if we call this function..
        JMP smartCover
        macro smartCover()
        print "Writing smartCover() to ",pc
        reset bytes
        BEQ .exit           ;Exit if none
        LDY #$FF    
        STY $F4             ;default to no bodyguards.
        JSR $51F9           ;Y = index of our highest intended target.
                            ;0, 2, 4, or 6 for characters.  8, 10, 12, 14, 16,
                            ;or 18 for monsters.
        STY $F8             ;save target index
        STZ $F2             ;Highest Bodyguard HP So Far = 0.  this makes the
                            ;first eligible bodyguard we check get accepted.
                            ;later ones may replace him/her if they have more
        LDX $336C,Y         ;Love Token - which target takes damage for you
        BMI .noLove         ;Branch if none do
        JSR evalKnight_skip ;consider this target as a bodyguard (skip Stamina
                            ;and Near Fatal checks)
        JSR newTarget       ;if it was valid, make it intercept the attack  
.noLove PLX
        LDA $3A36
        BNE .exit           ;Exit if Golem is active
        CPX #$08            ;Check attacker
        BCS .status         ;Branch if attacker is a monster
        CPX $F8
        BEQ .exit           ;Exit if Attacker = Target
        LDA $3EE4,X         ;Attacker status byte 1-2
        BIT #$2002
        BNE .heals          ;Branch if Muddled or Zombied
        LDA $3394,X         ;Check if Attacker is Charmed
        BMI .exit           ;If not Muddled, Zombied, or Charmed, this
                            ;attack was initiated by the player, so exit
.heals  LDA $11A9           ;Special weapon property
        AND #$00FF          ;Isolate bottom byte
        CMP #$0018          ;Check "Curative Attributes"
        BEQ .exit           ;Exit if set
        SEP #$20         
        LDA $11A1           ;Attack element(s)
        PLA                 ;Copy to high byte
        REP #$20
        AND $3BCC,Y         ;Target absorbed/immune elements
        BNE .exit           ;If any absorbed or nullified, exit
.status LDA $3EE4,Y         ;Target status byte 1-2
        BIT #$04DA
        BNE .exit           ;Branch if Death, Petrify, Clear, Zombie, Magitek,
                            ;or Image
.seize  LDA $3358,Y         ;$3359 = who is Seizing you
        BPL .exit           ;Branch if target is seized
        LDA #$000F          ;Load all characters as potential bodyguards        
	.cover  CPY #$08
        BCC .saveBg         ;Branch if target is character
        TDC                 ;Null all potential bodyguards
.saveBg STA $F0             ;Save potential bodyguards
        LDA $3018,Y         ;bit representing target
        ORA $3018,X         ;bit representing attacker
        TRB $F0             ;Clear attacker and target from potential
        JMP trueKnightAndLoveToken_contd
.exit   PLX
        print "smartCover: ",bytes," bytes written, ending at ",pc
	.contd  LDX #$12
.loop   LDA $3C57,X         ;High byte = Relic Effects 3
        ASL #2              ;Check bit 6 (True Knight)
        BCC .next           ;Branch if no True Knight effect                
        LDA $3018,X
        BIT $F0
        BEQ .next           ;Branch if this candidate isn't on the same
                            ;team as the target
        JSR evalKnight      ;consider them as candidate bodyguard.  if they're
                            ;valid and their HP is >= past valid candidates,
                            ;they become the new frontrunner.
.next   DEX
        BPL .loop           ;Do for all characters and monsters
        LDA $F2
        BEQ .exit           ;Exit if no bodyguard found [or if the selfless
                            ;soul has 0 HP, which shouldn't be possible outside
                            ;of bugs].
        JSR newTarget       ;make chosen bodyguard -- provided there was one --
                            ;intercept attack.  if somebody's already been
                            ;slated to intercept it [i.e. due to Love Token],
                            ;the True Knight will sensibly defer to them.
.exit   PLX
;Make chosen bodyguard intercept attack, provided one hasn't been marked to do
;so already.
        LDX $F4
        BMI .exit           ;exit if no bodyguard found
        CPY $F8
        BNE .exit           ;exit if $F8 no longer points to the original
                            ;target, which means we've already assigned a
                            ;bodyguard with this function.
        STX $F8             ;save bodyguard's index
        STY $A8             ;save intended target's index
        LSR $A8             ;.. but for the latter, use 0,1,2,etc rather
                            ;than 0,2,4,etc
        LDA $3018,X
        STA $B8             ;save bodyguard as the new target of attack
        SEP #$20
        LDA $3AA1,X
        BIT #$02
        BEQ .noDef          ;Branch if not Defending
        JSR $0A41           ;Clear Defending flag
        JSR $0A3C           ;Relax Defending pose
.noDef  REP #$20
.exit   RTS
;Consider candidate bodyguard for True Knight or Love Token
        LDA #$0020
        BIT $3AA1,X
        BNE .exit           ;Exit if guard is in back row
        LDA $3EE5,Y         ;Low byte = Status byte 2
        LSR #2              ;Check bit 1 (Near Fatal)
        BCS .skip           ;Skip Stamina check if target Near Fatal        
        LDA $3AA1,Y
        BIT #$0020
        BEQ .exit           ;Exit if target is in back row
        LDA $3EE5,X         ;Knight's Status byte 2
        LSR #2              ;Check Near Fatal
        BCS .exit           ;If Knight is Near Fatal, exit
        SEP #$20                
        LDA #$C0            ;192
        JSR $4B65           ;Random: 0 to 191
        CMP $3B40,X         ;Stamina
        REP #$20
        BCS .exit           ;Exit if Stamina was lower
.skip                       ;Love Token enters here
        LDA $3AA0,X
        BCC .exit           ;Exit function if entity not present in battle?
        LDA $3358,X         ;$3359 = who is Seizing you
        BPL .exit           ;Exit if you're Seized
        LDA $336B,Y         ;Love Token - which target takes damage for you
        BMI .noLove         ;Branch if none do
        LDA $3EE4,X         ;Bodyguard's status
        BIT #$A0DA          ;Death, Petrify, Clear, Zombie, Sleep, Muddled,
                            ;Dark, Magitek, Image, Berserk
        BNE .exit
        BRA .love
.noLove LDA $3EE4,X         ;Bodyguard's status
        BIT #$B4DB          ;Death, Petrify, Clear, Zombie, Sleep, Muddled,
                            ;Dark, Magitek, Image, Berserk
        BNE .exit           ;Exit if any set
.love   LDA $3EF8,X     
        BIT #$3211          ;Dance, Stop, Freeze, Spell Chant, Hide
        BNE .exit           ;Exit if any set
        LDA $3018,X
        TSB $A6             ;make this potential guard jump in front of the
                            ;target, can accompany others
        LDA $3BF4,X         ;HP of this potential bodyguard
        CMP $F2         
        BCC .exit           ;branch if it's not >= the highest HP of the other
                            ;bodyguards considered so far for this attack.
        STA $F2             ;if it is, save this entity's HP as the highest
                            ;HP so far.
        STX $F4             ;and this entity becomes the new bodyguard.
.exit   RTS
    print "Cover function end: ",pc
print "Vanilla Cover ends: c212f4"
    ;Check for Covered attacks in Hit Determination
;Disable Dog Block if attack was Covered
org $C22282
        LDA $3EF9,Y
        BPL C22293            ;Branch if not dog block
        JSR skipDogBlock
        macro skipDogBlock()
        print "Writing skipDogBlock() to ",pc
        reset bytes
        CPY $F4             ;Is target = bodyguard?
        BNE .exit           ;If not, return
        CLC                 ;Otherwise, set carry = 0, ie.
.exit   JMP $4B53           ;Random: carry 0 or 1          
        print "skipDogBlock: ",bytes," bytes written, ending at ",pc
;        BCC C22293          ;50% chance
;        LDA #$40      
;        STA $FE             ;Set dog block animation flag
org $C22293
    ;Halve Evasion if attack was Covered
org $C22345
        JSR halveEvasion    ;Get Evade
        macro halveEvasion()
        print "Writing halveEvasion() to ",pc
        reset bytes
        halveEvasion:       ;Y = target of attack
        CPY $F4             ;Index of bodyguard ($FF if no bodyguard)
        BNE .exit           ;If not the same as target, exit
        LDA #$FF            ;255
        SBC $3B54,Y         ;255 - (255 - Evade * 2 + 1)
                            ;(= Evade * 2 - 1)
        INC                 ;Evade * 2
        LSR                 ;Evade
        LSR                 ;Evade / 2
        JMP $2861           ;New blockvalue from halved Evade
.exit   LDA $3B54,Y         ;(255 - Evade * 2 + 1)
        print "halveEvasion: ",bytes," bytes written, ending at ",pc
    org !smartCover
org !halveEvade
org !noDogBlock

Share this post

Link to post
Share on other sites

Scan doesn't trigger counters


NOTE: I'm unsure of whether this conflicts with @darknil's scan code. Anyway, just find a way to fit a STZ $341A in the Scan target effect code.


;No Scan counters

!freespace = $C2xxxx    ; Requires 6 bytes of free space in C2

; Scan effect
org $C23C5B
JSR clearCounterVar

; X-Zone, etc
org $C23C8C
C23C8C: STZ $341A       ; Clear variable that enables counterattacks

; New code
org !freespace
LDA $3C80,Y             ; (Moved code)
JMP C23C8C              ; Go to X-Zone, etc code


Edited by seibaby

Share this post

Link to post
Share on other sites

Include a music change to AI command FA 06 (characters run left)

@Synchysi this replaces the SrBehemoth fix from Madsiur

	; Animation script $025C: Misc. Monster Animation $06: Characters Run Right to Left (bg1)
; Include a change to boss battle music
!freespace = $D0CF4A    ; Requires 18 bytes in bank D0
	; Relocate animation script
org !freespace
        db $00,$20                ; speed 1, align to center of character/monster
        db $D1,$01                ; invalidate character/monster sprite priority
        db $C7,$0B,$10,$14,$FF    ; SPC command $10, $14, $FF (play boss music)
        db $89,$37                ; loop start (55 times)
        db $80,$79                ; command $80/$79
        db $0F                    ; [$0F]
        db $8A                    ; loop end
        db $80,$7B                ; command $80/$7B
        db $FF                    ; end of script
; Update the pointer
org $D1EF90
dw anim_script_025c

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now