;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The first GFX routine ; It uses alternate OAM slots for certain game modes ; $05, $06 and $07 are assumed to be the current tile's size, current tile's properties and current tile respectively ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA_029FA3: ; This table is loaded prior to running GFXRoutine2 to determine the normal OAM slots db $05,$03 DATA_029FA5: ; The second table for OAM slots db $02,$02,$02,$02,$02,$02,$F8,$FC db $A0,$A4 GFXRoutine1: LDY.w DATA_029FA5,X ; Load the extended sprite's OAM slot to Y LDA $1747,X ;\ Load the exsprite's X speed... AND #$80 ; | find whether the speed is negative or positive... LSR ; | shift right once... STA $00 ;/ and store the result to use for properties (#$00 is right, #$40 is left) LDA $171F,X ;\ Subtract the X screen boundary from the exsprite's X position... SEC ; | SBC $1A ; | CMP #$F8 ; | and if the new value places it offscreen horizontally... BCS MainLabel12 ;/ destroy it STA $0300,Y ; Otherwise, store the result to the exsprite's onscreen X position LDA $1715,X ;\ Subtract the Y screen boundary from the exsprite's Y position... SEC ; | SBC $1C ; | CMP #$F0 ; | and if the new value places it offscreen vertically... BCS MainLabel12 ;/ destroy it STA $0301,Y ; Otherwise, store the result to the exsprite's onscreen Y position LDA $1779,X ;\ Store "exsprite goes behind scenery" flag to $01 STA $01 ;/ LDA $07 ;\ Load $07 (the current tile, set before the JSL)... STA $0302,Y ;/ and set the exsprite's tile accordingly LDA $06 ;\ Load $07 (the current tile properties, set before the JSL)... EOR $00 ; | factor in the direction byte for the properties ORA $64 ; | and the level's properties STA $0303,Y ;/ and store the result as the current tile properties LDX $01 ;\ If the exsprite doesn't go behind stuff... BEQ MainLabel13 ; | branch ahead AND #$CF ; | Otherwise, set bit 5 of the earlier result to zero... ORA #$10 ; | and bit 4 to one STA $0303,Y ;/ and store the new result MainLabel13: TYA ;\ LSR ; | Divide the OAM slot by 4 LSR ; | TAY ;/ LDA $05 ;\ Load $05 (the current tile's size, set before the JSL)... STA $0460,Y ;/ and set the tile size (#$00 is 8x8, #$02 is 16x16) LDX $15E9 ; X = Sprite index RTL ; Return MainLabel12: LDA #$00 ;\ Clear extended sprite STA $170B,X ;/ RTL ; Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The second GFX routine ; It runs most of the time, using the normal extended sprite OAM slots ; $05, $06 and $07 are assumed to be the current tile's size, current tile's properties and current tile respectively ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GFXRoutine2: LDA $1747,X ;\ Load X speed... AND #$80 ; | find exsprite's direction... EOR #$80 ; | LSR ; | (right is #$00, left is #$01) STA $00 ;/ and store to $00 LDA $171F,X ;\ Find the exsprite's X position low byte... SEC ; | SBC $1A ; | Subtract the X screen boundry low byte... STA $01 ;/ and store to $01 LDA $1733,X ;\ Check if exsprite's offscreen horizontally... SBC $1B ; | BNE DestroySprite ;/ destroy it if so LDA $1715,X ;\ Find the exsprite's Y position low byte... SEC ; | SBC $1C ; | Subtract the Y screen boundry low byte... STA $02 ;/ and store to $02 LDA $1729,X ;\ SBC $1D ; | Check if exsprite's offscreen vertically... BNE DestroySprite ;/ destroy it if so LDA $02 ;\ If exsprite is below screen... CMP #$F0 ; | BCS DestroySprite ; | destroy it STA $0201,Y ;/ otherwise, store position relative to Y screen boundry to Y tile position LDA $01 ;\ and do the same for X STA $0200,Y ;/ LDA $1779,X ;\ Store "exsprite goes behind scenery" flag to $01 STA $01 ;/ LDA $07 ;\ Load $07 (the current tile, set before the JSL)... STA $0202,Y ;/ and set the exsprite's tile accordingly LDA $06 ;\ Load $07 (the current tile properties, set before the JSL)... EOR $00 ; | factor in the direction byte for the properties ORA $64 ; | and the level's properties STA $0203,Y ;/ and store the result as the current tile properties LDX $01 ;\ If the exsprite doesn't go behind stuff... BEQ CODE_02A204 ; | branch ahead AND #$CF ; | Otherwise, set bit 6 of the earlier result to zero... ORA #$10 ; | and bit 5 to one STA $0203,Y ;/ and store the new result CODE_02A204: TYA ;\ LSR ; | Divide the OAM slot by 4 LSR ; | TAY ;/ LDA $05 ;\ Load $05 (the current tile's size, set before the JSL)... STA $0420,Y ;/ and set the tile size (#$00 is 8x8, #$02 is 16x16) LDX $15E9 ; X = Sprite index RTL ; Return DestroySprite: LDA #$00 ;\ Clear extended sprite STA RAM_ExSpriteNum,X ;/ RTL ; Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The position update routines ; The first reads and updates X values, the second Y values ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PositionUpdateX: TXA ;\ Add 10 to the sprite slot... CLC ; | ADC #$0A ; | TAX ; | JSL PositionUpdateY ;/ so PositionUpdateY will read X values instead of Y LDX $15E9 ; X = Sprite index RTL ; Return PositionUpdateY: ; Set new positions based on speeds LDA $173D,X ASL ASL ASL ASL CLC ADC $1751,X STA $1751,X PHP LDY #$00 LDA $173D,X LSR LSR LSR LSR CMP #$08 BCC PositionUpdateY2 ORA #$F0 DEY PositionUpdateY2: PLP ADC $1715,X STA $1715,X TYA ADC $1729,X STA $1729,X RTL ; Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The object interaction routine ; It sets the carry when hitting a solid object from any side ; It also handles slope interaction, moving the exsprite accordingly ; It is very confusing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InteractRoutine1: STZ $0F ; Set these variables up for math routines STZ $0E STZ $0B STZ $1694 LDA $140F ;if Reznor timer is set BNE InteractLabel1 ;branch LDA $0D9B ;if game mode is normal level BPL InteractLabel1 ;branch AND #$40 ;if game mode has bit #$01 set BEQ InteractLabel2 LDA $0D9B CMP #$C1 BEQ InteractLabel1 LDA $1715,X CMP #$A8 RTL ; Return InteractLabel2: LDA $171F,X CLC ADC #$04 STA $14B4 LDA $1733,X ADC #$00 STA $14B5 LDA $1715,X CLC ADC #$08 STA $14B6 LDA $1729,X ADC #$00 STA $14B7 JSL $01CC9D LDX $15E9 ; X = Sprite index RTL ; Return InteractLabel1: JSL InteractLabel3 ROL $0E LDA $1693 STA $0C LDA $5B BPL InteractLabel4 INC $0F LDA $171F,X PHA CLC ADC $26 STA $171F,X LDA $1733,X PHA ADC $27 STA $1733,X LDA $1715,X PHA CLC ADC $28 STA $1715,X LDA $1729,X PHA ADC $29 STA $1729,X JSL InteractLabel3 ROL $0E LDA $1693 STA $0D PLA STA $1729,X PLA STA $1715,X PLA STA $1733,X PLA STA $171F,X InteractLabel4: LDA $0E CMP #$01 RTL ; Return InteractLabel3: LDA $0F ; INC A ; Set $0F to #$01... AND $5B ; If bit #$07 of screen mode isn't set (horiz. level) BEQ InteractLabel5 ; Branch LDA $1715,X ;\ Load the low byte of the exsprite's y position... CLC ; | ADC #$08 ; | add #$08... STA $98 ; | and store it to the block x low byte for later use. AND #$F0 ; | Then take the first 4 bits of the result... STA $00 ;/ and store it to $00 so we can find the y position of the block the exsprite is touching later LDA $1729,X ;\ Load the high byte of the exsprite's y position... ADC #$00 ; | and add the carry from the last bit of math. CMP $5D ; | If the result places the exsprite offscreen vertically... BCS InteractLabel6 ; | branch to clear the carry flag and return from the routine. STA $03 ; | Otherwise, store the result to $03... STA $99 ;/ and the block x high byte. LDA $171F,X ;\ Load the low byte of the exsprite's x position... CLC ; | ADC #$04 ; | add #$04... STA $01 ; | then store it to $01... STA $9A ;/ and the block x low byte. LDA $1733,X ;\ Load the high byte of the exsprite's x position... ADC #$00 ; | and add the carry from the last bit of math. CMP #$02 ; | If the result places the exsprite offscreen horizontally... BCS InteractLabel6 ; | branch to clear the carry flag and return from the routine. STA $02 ; | Otherwise, store the result to $02... STA $9B ;/ and the block y high byte. LDA $01 ;\ Load the exsprite's x position low byte plus #$04... LSR ; | LSR ; | LSR ; | LSR ; | shift it right 4 times (divide it by 16)... ORA $00 ; | add the result with the first 4 bits of the exsprite's y position plus #$08... STA $00 ;/ and store the new result (now the coordinates of the block the exsprite is touching) back to $00 (bits of the result are now in the format YYYYXXXX) LDX $03 ;\ LDA $00BA80,X ; | Load from the table at $00BA80 in the ROM (check all.log) indexed by the high byte of the exsprite's y position LDY $0F ; | If this isn't the first run through this routine... BEQ InteractLabel7 ; | LDA $00BA8E,X ; | load from the table at $00BA8E in the ROM instead, again indexed by the high byte of the exsprite's y position InteractLabel7: ; | CLC ; | ADC $00 ; | Then, add it with the coordinates of the block the exsprite is touching... STA $05 ;/ and store the result to $05 LDA $00BABC,X ;\ Load from the table at $00BABC in the ROM, indexed by the high byte of the exsprite's y position LDY $0F ; | If this isn't the first run through this routine... BEQ InteractLabel18 ; | LDA $00BACA,X ; | load from the table at $00BACA in the ROM instead, again indexed by the high byte of the exsprite's y position InteractLabel18: ; | ADC $02 ; | Then add that with the high byte of the x position after adding #$04 to the low byte... STA $06 ;/ and store the result to $06 BRA InteractLabel8 InteractLabel6: CLC RTL ; Return InteractLabel5: LDA $1715,X ;\ Load the low byte of the exsprite's y position... CLC ; | ADC #$08 ; | add #$08... STA $98 ; | and store it to the block x low byte for later use. AND #$F0 ; | Then take the first 4 bits of the result... STA $00 ;/ and store it to $00 so we can find the y position of the block the exsprite is touching later LDA $1729,X ;\ Load the high byte of the exsprite's y position... ADC #$00 ; | and add the carry from the last bit of math. STA $02 ; | Store the result to $02 STA $99 ;/ and the block x high byte. LDA $00 ;\ If the exsprite is offscreen vertically... SEC ; | SBC $1C ; | CMP #$F0 ; | BCS InteractLabel6 ;/ branch to clear the carry flag and return from the routine. LDA $171F,X ;\ Load the low byte of the exsprite's x position... CLC ; | ADC #$04 ; | add #$04... STA $01 ; | then store it to $01... STA $9A ;/ and the block x low byte. LDA $1733,X ;\ Load the high byte of the exsprite's x position... ADC #$00 ; | and add the carry from the last bit of math. CMP $5D ; | BCS InteractLabel6 ; | STA $03 ; | STA $9B ;/ LDA $01 ;\ Load the exsprite's x position low byte plus #$04... LSR ; | LSR ; | LSR ; | LSR ; | shift it right 4 times (divide it by 16)... ORA $00 ; | add the result with the first 4 bits of the exsprite's y position plus #$08... STA $00 ;/ and store the new result (now the coordinates of the block the exsprite is touching) back to $00 (bits of the result are now in the format YYYYXXXX) LDX $03 ;\ LDA $00BA60,X ; | Load from the table at $00BA60 in the ROM, indexed by the high byte of the exsprite's x position LDY $0F ; | If this isn't the first run through this routine... BEQ InteractLabel9 ; | LDA $00BA70,X ; | Load from the table at $00BA70 in the ROM instead, indexed by the high byte of the exsprite's x position InteractLabel9: ; | CLC ; | ADC $00 ; | Then, add it with the coordinates of the block the exsprite is touching... STA $05 ;/ and store the result to $05 LDA $00BA9C,X ;\ Load from the table at $00BA9C in the ROM, indexed by the high byte of the exsprite's x position LDY $0F ; | If this isn't the first run through this routine... BEQ InteractLabel10 ; | LDA $00BAAC,X ; | Load from the table at $00BAAC in the ROM instead, indexed by the high byte of the exsprite's x position InteractLabel10: ; | ADC $02 ; | Then add that with the high byte of the y position after adding #$08 to the low byte... STA $06 ;/ and store the result to $06 InteractLabel8: LDA #$7E ; STA $07 ; LDX $15E9 ; X = Sprite index LDA [$05] ; Load from the address in [$05] to get the low byte of the Map16 number of the block the exsprite is touching STA $1693 ; ...and store it to the block # RAM temporarily INC $07 LDA [$05] ; Now load the high byte of the block's Map16 number JSL $06F7A0 ; Run Lunar Magic's inserted subroutine to find the block's Map16 behavior CMP #$00 ; After the subroutine, A is now the block's behavior BEQ InteractLabel11 LDA $1693 CMP #$11 BCC InteractLabel13 CMP #$6E BCC InteractLabel14 CMP #$D8 BCS InteractLabel17 LDY $9A STY $0A LDY $98 STY $0C JSL $00FA19 LDA $00 CMP #$0C BCS InteractLabel16 CMP [$05],Y BCC InteractLabel11 InteractLabel16: LDA [$05],Y STA $1694 PHX LDX $08 LDA $00E53D,X PLX STA $0B InteractLabel14: SEC RTL ; Return InteractLabel11: CLC RTL ; Return InteractLabel13: LDA $98 AND #$0F CMP #$06 BCS InteractLabel11 SEC RTL ; Return InteractLabel17: LDA $98 AND #$0F CMP #$06 BCS InteractLabel11 LDA $1715,X SEC SBC #$02 STA $1715,X LDA $1729,X SBC #$00 STA $1729,X JMP InteractLabel3