.include "defines.inc" .include "macros.inc" ; Prevent damage knockback on stairs. .code ; This sequence: ; next_PART ; .if PART=::CURPART ; .endif ; designates a patch ”component”. ; Each component is a separate object, ; that has its own set of imports/exports ; and rules concerning placement in the ROM. ; This particular assembler file consists of five components. ; In this case, ; - The first component is placed in a particular address in bank 1. ; - The second component is placed in a particular address in bank 3. ; - The third component is placed anywhere in bank 3. ; - The fourth component is placed in a particular address in bank 3. ; - The fifth component is placed anywhere in any PRG bank. ; These placements are controlled by the LINK_ directives. ; ; Due to technical reasons, the words “JSRF”, “JMPF” and “FIXUP_ABS” ; are used instead of “jsr”, “jmp” and “.word” respectively ; when the target address is an external label (a label that ; was not defined in this component). ; “FIXUP_ABS” creates a 16-bit address, “FIXUP_ABS24” creates a 24-bit one. ; Similarly, there exist LDA_ABS, ADC_ABSX, ADC_ADDRHI etc. ; commands for many common instructions that deal with absolute ; addresses where the address is not known at assembly time. ; These commands must NOT be used when dealing with addresses ; that ARE known at assembly-time. ; (Note: PAL_offset is known at assembly-time. ; It equals to 0 when compiling for NTSC, 77 when PAL.) ; ; I know that ca65/ld65 contains a built-in method to deal ; with externs, but my insertor cannot parse ca65’s .o files, ; so I have a different method that is based on user-defined ; macros that generate special symbols in a special segment, ; that my toolchain can parse from the map that ld65 produces. ; next_PART .if PART=::CURPART ; At 484F, change "lda #64; sta $4F8; ldy #0; lda $348,x; cmp $348; bcc +1; iny; sty ObjectFacingLeft; jmp SimonDamageKnockback" ; into "lda #0; ldy $348,x; cpy $348; rol; tay; jmp..." LINK_FREE_SPACE $483F, ($8855-$883F) LINK_IN_ADDR $483F ; Because the replacement code is not longer than the original code, ; we can put this code directly in the original location. DEBUG_LABEL Patch483F lda #0 ldy $348,x cpy $348 rol ; lda #0 + rol sets A=carry, carry=0. tay JSRF Trampoline_Jmp FIXUP_ABS24 SimonDamageKnockBack ; Calls from bank 1 .endif next_PART .if PART=::CURPART LINK_FREE_SPACE $C082, ($8090-$8082) LINK_IN_ADDR $C082 DEBUG_LABEL PatchC082 ; At C08A, change "lda #64; sta $4F8; lda $420; jsr $802B (bank 3); jmp SimonDamageKnockback" ; into "lda $420; eor #1; tay; jmp..." lda $420 eor #1 tay JSRF Trampoline_Jmp FIXUP_ABS24 SimonDamageKnockBack ; Calls from bank 3 .endif next_PART .if PART=::CURPART ; At CAD9, SimonExecuteCurrentAction9_StairsStand, ; add check for ObjectStunCounter ($4F8) ; If nonzero, rts instead of accepting any inputs ; This replaces 9 bytes at beginning of $CAD9 ; Simon will be stunned for 16 frames and invulnerable for 64 frames. LINK_FREE_SPACE $CAD9, 2+2+2+3 ; This function is placed in any random free spot in bank 3. ; The space that it used to occupy previously is marked free. LINK_IN_BANK 3 PUBLIC_LABEL SimonExecuteCurrentAction9_StairsStand lda $4F8 cmp #64-16 bcs :++ lda $F7 asl bpl :+ jmp $892B ; UnknownContextCAD9_JoyButtons_40_B_pressed_UseWeapon : jmp $8AE2 : rts .endif next_PART .if PART=::CURPART LINK_IN_PATCH $C1DC DEBUG_LABEL PatchC1DC ; Put a 16-bit point to SimonExecuteCurrentAction9_StairsStand FIXUP_ABS SimonExecuteCurrentAction9_StairsStand .endif next_PART .if PART=::CURPART LINK_FREE_SPACE ($1D36F-PAL_offset), ($D3AC-$D36F) ; This code is placed anywhere in the ROM. ; The linker decides the placement when it builds the patch, ; and it may vary depending on what else is getting linked. ; Here, the placement is set as “any bank”. ; A special trampoline is used to invoke the function, ; making cross-bank JSRs possible. LINK_IN_ANY_BANK PUBLIC_LABEL SimonDamageKnockBack ; Input: Y = new value for ObjectFacingLeft lda #64 ; 64 frames (#$40) sta $4F8 ; ObjectStunCounter (blinking counter) lda $300 ; Simon's pose ; Detect poses 06..09 and B0..B7 ; There are no poses for Simon beyond #$B7. cmp #$06 Jcc not_stairs cmp #$0A Jcc yes_stairs cmp #$B0 Jcs yes_stairs DEBUG_LABEL not_stairs tya ; Copies Y to A, sets NZ sta $420 ;ObjectFacingLeft ; If A=Y=0, we want A=0 and Y=1 ; If A=Y=1, we want A=0 and Y=255 Jeq right_dir ; Y is 1 dey ; Y becomes 0 tya ; so does A dey ; Y becomes 255 .byte $10 ; bpl dummy, branch never taken DEBUG_LABEL right_dir iny jsr $D36A - PAL_offset ;ItemMenuPauseScreen_CursorMovement_Horizontal_ByY lda #$FD ldy #$80 jsr $D362 - PAL_offset ; Object0_SetYVelocity16bit_from_AY lda #$1F jsr $DD87 - PAL_offset ; SetObjectIndexToAutomaticSpriteDataTable_to_A_for_Simon jsr $DCCA - PAL_offset ; DeleteSimonWhipObject setb $3D8, 6 ; ObjectCurrentActionType setb $4B0, $20 ; ObjectAIvar6 jsr $D3D3 - PAL_offset ; FindIfThereIsAFloatingPlatform Jcc no_platform setb $41, 0 sta $47A,x ; ? DEBUG_LABEL yes_stairs DEBUG_LABEL no_platform lda #$5F jmp AnyBankPlayTracks .endif